Pipe beruntun
- November 20, 2008 – 14:49
- Ditulis dalam C, Linux, Snippets, System Programming
- Dengan kaitkata C, file descriptor, Linux, pipe, POSIX, Programming, System Programming, UNIX
Di dalam UNIX Command, sering dipakai tanda “|”. Tanda “|” adalah pipe, maksudnya stdout dari sebuah program dapat menjadi stdin dari program yang lain. Di dalam C, fitur ini dapat diimplementasikan dengan fungsi pipe[]. Di contoh yang ada pada spesifikasi tersebut hanya menangani antara 2 proses.
#include #include int main[]{ int fildes[2]; const int BSIZE = 100; char buf[BSIZE]; ssize_t nbytes; int status; status = pipe[fildes]; switch [fork[]] { case -1: /* Handle error */ break; case 0: /* Child - reads from pipe */ close[fildes[1]]; /* Write end is unused */ nbytes = read[fildes[0], buf, BSIZE]; /* Get data from pipe */ /* At this point, a further read would see end of file ... */ close[fildes[0]]; /* Finished with pipe */ exit[EXIT_SUCCESS]; default: /* Parent - writes to pipe */ close[fildes[0]]; /* Read end is unused */ write[fildes[1], "Hello world\n", 12]; /* Write data on pipe */ close[fildes[1]]; /* Child will see EOF */ exit[EXIT_SUCCESS]; } }
Fungsi pipe ini akan menyambungkan input dari sebuah filedescriptor menjadi output pada filedescriptor lain. Input/output ini dibaca dengan menggunakan fungsi read[] dan write[].
Read More »
- September 6, 2008 – 01:55
- Ditulis dalam C, Snippets, System Programming
- Dengan kaitkata C, file descriptor, POSIX, Programming, System Programming, UNIX
File descriptor adalah sebuah abstraksi yang digunakan dalam pengaksesan file. Di dalam UNIX, file descriptor ini dilambangkan dalam sebuah integer. Untuk setiap proses, terdapat 3 file descriptor yang telah dimiliki.
- Standard input [stdin]. Bernilai 0.
- Standard output [stdout]. Bernilai 1.
- Standar error [stderr]. Bernilai 2.
File descriptor ini merupakan index pada tabel yang dimiliki kernel untuk menunjukkan file yang dibuka pada proses-proses yang berjalan.
Read More »
Saya agak bingung dengan tujuan dari ketiga file ini. Jika pemahaman saya benar, stdin
adalah file di mana suatu program menulis permintaannya untuk menjalankan tugas dalam proses, stdout
adalah file yang digunakan kernel untuk menulis outputnya dan proses yang memintanya mengakses informasi dari, dan stderr
adalah file di mana semua pengecualian dimasukkan. Saat membuka file-file ini untuk memeriksa apakah ini benar-benar terjadi, saya menemukan tidak ada yang menyarankan
begitu!
Apa yang ingin saya ketahui adalah apa sebenarnya tujuan dari file-file ini, benar-benar membodohi jawaban dengan jargon teknologi yang sangat sedikit!
Input standar - ini adalah pegangan file yang dibaca oleh proses Anda untuk mendapatkan informasi dari Anda.
Output standar - proses Anda menulis informasi normal ke pegangan file ini.
Kesalahan standar - proses Anda menulis informasi kesalahan ke pegangan file ini.
Itu hampir sama bodohnya seperti yang saya bisa lakukan :-]
Tentu saja, itu kebanyakan berdasarkan konvensi. Tidak ada yang menghentikan Anda dari menulis informasi kesalahan Anda ke output standar jika Anda mau. Anda bahkan dapat menutup ketiga pegangan file secara total dan membuka file Anda sendiri untuk I/O.
Ketika proses Anda dimulai, itu seharusnya sudah memiliki pegangan ini terbuka dan itu hanya bisa membaca dari dan/atau menulis kepada mereka.
Secara default, mereka mungkin terhubung ke perangkat terminal Anda [misalnya, /dev/tty
] tetapi shell akan memungkinkan Anda untuk mengatur koneksi antara pegangan ini dan file dan/atau perangkat tertentu [atau bahkan jaringan pipa ke proses lain] sebelum Anda proses dimulai [beberapa manipulasi yang mungkin agak pintar].
Contohnya adalah:
my_prog errorfile | grep XYZ
yang mana akan:
- buat proses untuk
my_prog
. - buka
inputfile
sebagai input standar Anda [pegangan file 0]. - buka
errorfile
sebagai kesalahan standar Anda [pegangan file 2]. - buat proses lain untuk
grep
. - lampirkan output standar
my_prog
ke input standargrep
.
Berikan komentar Anda:
Ketika saya membuka file-file ini di folder/dev, kenapa saya tidak pernah melihat output dari proses yang berjalan?
Itu karena mereka bukan file normal. Sementara UNIX menyajikan semuanya sebagai file dalam sistem file di suatu tempat, itu tidak membuatnya jadi pada level terendah. Sebagian besar file dalam hierarki /dev
adalah karakter atau blokir perangkat, yang secara efektif merupakan driver perangkat. Mereka tidak memiliki ukuran tetapi mereka memiliki nomor perangkat utama dan kecil.
Saat Anda membukanya, Anda terhubung ke driver perangkat daripada file fisik, dan driver perangkat cukup pintar untuk mengetahui bahwa proses terpisah harus ditangani secara terpisah.
Hal yang sama berlaku untuk sistem file Linux /proc
. Itu bukan file asli, hanya gateway yang dikontrol ketat untuk informasi kernel.
Akan lebih benar untuk mengatakan bahwa stdin
, stdout
, dan stderr
adalah "I/O stream" daripada
file. Seperti yang Anda perhatikan, entitas ini tidak tinggal di sistem file. Tetapi filosofi Unix, sejauh menyangkut I/O, adalah "semuanya adalah file". Dalam praktiknya, itu benar-benar berarti bahwa Anda dapat menggunakan fungsi dan antarmuka pustaka yang sama [printf
, scanf
, read
, write
, select
, dll.] Tanpa khawatir tentang apakah aliran I/O terhubung ke keyboard, file disk, file soket, pipa, atau abstraksi I/O lainnya.
Sebagian besar program perlu membaca input, menulis
keluaran, dan mencatat kesalahan, sehingga stdin
, stdout
, dan stderr
sudah ditentukan sebelumnya untuk Anda, sebagai kenyamanan pemrograman. Ini hanya konvensi, dan tidak diberlakukan oleh sistem operasi.
Sebagai pelengkap dari jawaban di atas, berikut adalah ringkasan tentang Pengalihan:
EDIT: Grafik ini tidak sepenuhnya benar tetapi saya tidak yakin mengapa ...
Grafik mengatakan 2> & 1 memiliki efek yang sama dengan &>
ls Documents ABC > dirlist 2>&1
#does not give the same output as
ls Documents ABC > dirlist &>
Saya khawatir pengertian Anda sepenuhnya mundur. :]
Pikirkan "standar dalam", "keluar standar", dan "kesalahan standar" dari perspektif program, bukan dari perspektif kernel.
Ketika suatu program perlu mencetak keluaran, biasanya ia mencetak ke "out standar". Suatu program biasanya mencetak keluaran ke standar dengan printf
, yang mencetak HANYA ke standar keluar.
Ketika suatu program perlu mencetak informasi kesalahan [tidak harus pengecualian, itu adalah konstruksi bahasa pemrograman, dikenakan pada tingkat yang jauh lebih tinggi],
itu biasanya dicetak ke "kesalahan standar". Biasanya demikian dengan fprintf
, yang menerima aliran file untuk digunakan saat mencetak. Aliran file dapat berupa file apa saja yang dibuka untuk ditulis: standar keluar, kesalahan standar, atau file lain apa pun yang telah dibuka dengan fopen
atau fdopen
.
"standar dalam" digunakan ketika file perlu membaca input, menggunakan fread
atau fgets
, atau getchar
.
File-file ini dapat dengan mudah diarahkan dari Shell, seperti ini:
cat /etc/passwd > /tmp/out # redirect cat's standard out to /tmp/foo
cat /nonexistant 2> /tmp/err # redirect cat's standard error to /tmp/error
cat < /etc/passwd # redirect cat's standard input to /etc/passwd
Atau, seluruh enchilada:
cat < /etc/passwd > /tmp/out 2> /tmp/err
Ada dua peringatan penting: Pertama, "standar dalam", "standar keluar", dan "kesalahan standar" hanyalah sebuah konvensi. Mereka adalah konvensi sangat kuat, tetapi itu semua hanya kesepakatan bahwa sangat bagus untuk dapat menjalankan program seperti ini: grep echo /etc/services | awk '{print $2;}' | sort
dan memiliki output standar dari setiap program yang terhubung ke input standar dari program berikutnya di dalam pipa.
Kedua, saya telah memberikan fungsi
standar ISO C untuk bekerja dengan stream file [FILE *
objek] - pada level kernel, semuanya adalah deskriptor file [int
referensi ke tabel file] dan banyak operasi level yang lebih rendah seperti read
dan write
, yang tidak melakukan penyanggaan bahagia fungsi-fungsi ISO C. Saya pikir untuk membuatnya tetap sederhana dan menggunakan fungsi yang lebih mudah, tapi saya pikir semua yang sama Anda harus tahu alternatifnya. :]
stdin
Membaca input melalui konsol [mis. Input Keyboard]. Digunakan dalam C dengan scanf
scanf[, ...];
stdout
Menghasilkan output ke konsol. Digunakan dalam C dengan printf
printf[, ...];
stderr
Menghasilkan output 'error' ke konsol. Digunakan dalam C dengan fprintf
fprintf[stderr, , ...];
Pengalihan
Sumber untuk stdin dapat dialihkan. Misalnya, alih-alih berasal dari input keyboard, itu dapat berasal dari file [echo < file.txt
], atau program lain [ps | grep
].
Tujuan untuk stdout, stderr juga dapat diarahkan.
Misalnya stdout dapat dialihkan ke file: ls . > ls-output.txt
, dalam hal ini output ditulis ke file ls-output.txt
. Stderr dapat dialihkan dengan 2>
.
Saya pikir orang yang mengatakan stderr
harus digunakan hanya untuk pesan kesalahan yang
menyesatkan.
Ini juga harus digunakan untuk pesan informatif yang dimaksudkan untuk pengguna yang menjalankan perintah dan bukan untuk konsumen hilir potensial data [yaitu jika Anda menjalankan pipa Shell chaining beberapa perintah Anda tidak ingin pesan informatif seperti "mendapatkan item 30 dari 42424 "muncul di stdout
karena mereka akan membingungkan konsumen, tetapi Anda mungkin masih ingin pengguna melihatnya.
Lihat ini untuk alasan historis:
"Semua program menempatkan diagnostik pada output standar. Ini selalu menyebabkan masalah ketika output diarahkan ke file, tetapi menjadi tidak dapat ditoleransi ketika output dikirim ke proses yang tidak curiga. Meskipun demikian, tidak mau melanggar kesederhanaan input-standar- model output-standar, orang mentolerir keadaan ini melalui v6. Tak lama kemudian Dennis Ritchie memotong simpul Gordian dengan memperkenalkan file kesalahan standar. Itu tidak cukup memadai. Dengan pipa penyaluran, diagnostik dapat berasal dari beberapa program yang berjalan secara bersamaan. untuk mengidentifikasi diri mereka sendiri. "
Menggunakan ps -aux mengungkapkan proses saat ini, yang semuanya terdaftar di/proc/as/proc/[pid] /, dengan memanggil cat/proc/[pid]/fd/0 itu mencetak apa pun yang ditemukan dalam output standar dari proses itu saya pikir. Jadi mungkin,
/ proc/[pid]/fd/0 - File Output Standar
/proc/[pid]/fd/1 - File Input Standar
/proc/[pid]/fd/2 - File Kesalahan Standar
sebagai contoh
Tetapi hanya bekerja dengan baik untuk/bin/bash proses lain umumnya tidak ada dalam 0 tetapi banyak kesalahan ditulis dalam 2
Untuk informasi otoritatif tentang file-file ini, periksa halaman manual, jalankan perintah pada terminal Anda.
$ man stdout
Tetapi untuk jawaban sederhana, setiap file untuk:
stdout untuk streaming
stdin untuk input stream
stderr untuk kesalahan pencetakan atau pesan log.
Setiap program unix memiliki masing-masing aliran tersebut.
stderr tidak akan melakukan IO Penyangga cache jadi jika aplikasi kita perlu mencetak info pesan penting [beberapa kesalahan, pengecualian] untuk menghibur atau untuk mengarsipkan menggunakannya di mana seperti menggunakan stdout untuk mencetak info log umum seperti yang digunakan IO buffering cache ada kemungkinan bahwa sebelum menulis pesan kami ke aplikasi file mungkin ditutup, meninggalkan kompleks debugging
File dengan buffering terkait disebut stream dan dinyatakan sebagai pointer ke jenis FILE yang ditentukan. Fungsi fopen [] membuat data deskriptif tertentu untuk streaming dan mengembalikan pointer untuk menunjuk aliran dalam semua transaksi lebih lanjut. Biasanya ada tiga stream terbuka dengan pointer konstan yang dideklarasikan di header dan dikaitkan dengan file open standar. Pada startup program tiga aliran sudah ditentukan sebelumnya dan tidak perlu dibuka secara eksplisit: input standar [untuk membaca input konvensional], output standar [untuk penulisan output konvensional], dan standard error [untuk menulis output diagnostik]. Ketika dibuka, aliran kesalahan standar tidak sepenuhnya buffer; input standar dan output stream standar sepenuhnya buffered jika dan hanya jika aliran dapat ditentukan untuk tidak merujuk ke perangkat interaktif
//www.mkssoftware.com/docs/man5/stdio.5.asp