• Tidak ada hasil yang ditemukan

I/O Low-Level

Dalam dokumen Buku bhs pemrograman Q Equational 2018 (Halaman 182-187)

10 fungsi Built-In

11. Pustaka Standar

12.8 I/O Low-Level

Fungsi-fungsi ini menyediakan operasi untuk memanipulasi langsung file-file di tingkatan file descriptor. Untuk suatu uraian yang semakin dekat dari operasi berikut, kita menunjuk pembaca kepada halaman-halaman UNIX manual yang sesuai.

public extern open NAME FLAGS MODE; // membuat suatu descriptor yang baru

public extern close FD; // menutup suatu descriptor public extern dup FD, dup2 OLDFD NEWFD; // menyalin suatu descriptor

public extern pipe; // membuat satu pipa yang tak dikenal

public extern fstat FD; // perencanaa descriptor public extern fchdir FD; // mengubah direktori (U) public extern fchmod FD MODE; // merubah modus file (U)

public extern fchown FD UID GID; // menetapkan kepemilikan file (U) public extern ftruncate FD LEN; // memotong suatu file (U)

public extern fsync FD, fdatasync FD; // sync file yang diberi (U)

Operasi yang berikut dapat digunakan di file descriptors dan file object. Mereka membaca dan menulis data biner yang diwakili sebagai string-string byte (lihat Byte Strings), menyediakan satu menghubung ke fungsi read/write(2) dan fread/fwrite(3) sistem itu. Fungsi bread

mengembalikan suatu string byte dari ukuran yang diberi yang dibaca dari file yang diberi. Catatan bahwa string byte yang dikembalikan boleh sebenarnya adalah lebih pendek dibanding byte-byte SIZE, misalnya, akhir dari file sudah dicapai atau tidak cukup masukan sekarang ini yang tersedia di suatu pipa. Fungsi bwrite mengembalikan banyaknya byte-byte yang benar- benar ditulis yang biasanya ukuran dari string byte kecuali jika satu kesalahan terjadi. Fungsi- fungsi gagal jika satu kesalahan terjadi sebelum apapun dibaca atau ditulis. Hal itu merupakan tanggung jawab aplikasi untuk memeriksa kondisi error dan menangani mereka dalam satu cara yang sesuai.

public extern bread FD SIZE; // membaca suatu string byte public extern bwrite FD DATA; // menulis suatu string byte

Sebagai contoh, fungsi yang berikut menggunakan bread dan bwrite untuk menyalin satu masukan kepada satu file keluaran, menggunakan gumpal-gumpal dari 8192 byte pada waktu yang sama:

fcopy F G = () if bwrite G (bread F 8192) < 8192; = fcopy F G otherwise;

file penunjuk dari suatu descriptor dapat diposisikan dengan lseek. Di dalam perbedaan kepada fseek, fungsi ini mengembalikan offset yang baru. Untuk menentukan posisi yang ada, karenanya anda dapat menggunakan satu ekspresi seperti `lseek FD 0 SEEK_CUR'.

public extern lseek FD POS WHENCE;

Beberapa rutinitas terkait dengan terminal juga disediakan:

public extern isatty FD; // apakah descriptor suatu terminal?

Yang berikut adalah UNIX-specific:

public extern ttyname FD; // terminal yang berhubungan dengan descriptor

public extern ctermid; // nama dari terminal pengendalian public extern openpty, forkpty; // operasi terminal pseudo

Fungsi openpty mengembalikan suatu pasangan (MASTER, BUDAK) dari file descriptors dibuka untuk membaca dan menulis di sebuah "terminal yang pura-pura". MASTER digunakan di dalam proses pengendalian, selagi SLAVE dapat digunakan untuk stream I/O standar di suatu proses anak. Fungsi forkpty mengkombinasikan openpty dengan fork dan membuat alat slave mengontrol terminal dari proses anak; itu mengembalikan suatu pasangan (PID, GURU), di mana PID adalah nol di dalam proses anak dan proses id dari anak di dalam induk, dan MASTER adalah master akhir dari terminal yang pura-pura untuk digunakan oleh induk. Fungsi-fungsi ini biasanya digunakan untuk menerapkan aplikasi-aplikasi yang memandu program-program melalui suatu antar muka emulasi terminal lain.

Di sistem UNIX, clib juga menyediakan akses kepada operasi fcntl yang berikut (lihat Bagian 2 manual UNIX):

parameter ARG dari fcntl bergantung pada jenis dari perintah CMD yang dieksekusi. Tersedia kode perintah dan nilai-nilai relevan lain yang digambarkan sebagai variabel global, seperti yang didaftarkan di bawah. Tanda-tanda bersifat pemisahan menurut nilai bit simbolik yang di daftar di bawah. (itu mengikuti nilai-nilai yang ada di kebanyakan sistem. Implementasi- implementasi spesifik boleh menyediakan tanda-tanda tambahan.)

public var const

// kode perintah fcntl

F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK, F_SETLK, F_SETLKW,

// tipe kunci

F_RDLCK, F_WRLCK, F_UNLCK,

// modus file akses dan bitmask akses mode O_RDONLY, O_WRONLY, O_RDWR, O_ACCMODE, // tanda file descriptor

FD_CLOEXEC, // tanda status

O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_NONBLOCK, O_NDELAY, O_NOCTTY, O_BINARY;

Yang berikut Tipe-tipe dari perintah-perintah diterapkan:

fcntl FD F_DUPFD ARG // menyalin suatu file descriptor fcntl FD F_GETFD () // mendapatkan tanda file descriptor

fcntl FD F_SETFD FLAGS // menetapkan tanda file descriptor fcntl FD F_SETFD () // mendapat status modus flags/access

fcntl FD F_SETFD FLAGS // menetapkan tanda status

fcntl FD F_GETLK (TYPE,POS,LEN[,WHENCE]) // file query mengunci informasi fcntl FD F_SETLK (TYPE,POS,LEN[,WHENCE]) // menetapkan satu kunci file laporan

fcntl FD F_SETLKW (TYPE,POS,LEN[,WHENCE]) // varian pengeblokan dari F_SETLK

lima fungsi perintah Pertama untuk menyalin descriptors dan untuk mendapat kembali dan mengubah file descriptor dan tanda status. Sisa perintah digunakan untuk penguncian file laporan. Suatu kunci file ditetapkan sebagai suatu yang rangkap tiga (JENIS, POS, L) atau mengalikan dengan empat (JENIS, POS, L, DARI MANA), di mana TYPE adalah jenis dari kunci (F_RDLCK, F_WRLCK atau F_UNLCK untuk kunci baca, kunci menulis dan membuka kunci, berturut-turut), POS posisi di dalam file, LEN banyaknya byte-byte untuk dikunci (0 berarti sampai ke ujung file) dan WHENCE menetapkan bagaimana argument POS diinterpretasikan. (Parameter ini mempunyai maksud yang sama seperti fungsi fseek dan lseek, lihat di atas. Jika WHENCE dihilangkan, default menjadi SEEK_SET, yaitu., posisi-posisi absolut.) Nilai yang dikembalikan oleh perintah F_GETLK adalah uraian kunci dengan TYPE yang di-set ke F_UNLCK jika kunci yang diberi akan diterima, dan uraian suatu kunci pemblokan yang ada kunci meminta cara lainnya. (Kemudian kasus nilai hasil sebenarnya suatu

quadruple, dengan id dari suatu proses sekarang ini memiliki suatu kunci yang berlawanan di dalam komponen yang terakhir.)

Catatan bahwa operasi I/O standar menggunakan I/O buffered secara langsung yang mungkin menghalangi penguncian record. Oleh karena itu di dalam aplikasi-aplikasi yang memerlukan penguncian record yang individu anda perlu bekerja dengan operasi yang low-level (terbuka, bwrite, dll.) sebagai gantinya.

fungsi memilih yang berikut menunggu satu set file-file untuk mengubah status I/O. Catatan bahwa operasi ini tersedia di Windows sebagai bagian dari antar muka socket, tetapi itu hanya berlaku bagi socket di sana.

public extern select FILES;

Masukan itu adalah suatu tuple (IN, OUT, ERR, TIMEOUT) terdiri dari tiga daftar file descriptors dan/atau file object untuk diamati, dan satu pilihan penetapan nilai bilangan bulat atau floating point suatu timeout dalam hitungan detik. Fungsi mengembalikan secepat suatu anggota IN atau OUT tersedia bagi pelaksanaan satu operasi I/O (tanpa pengeblokan), atau satu kondisi error yang diberi isyarat untuk suatu anggota ERR. Nilai yang dikembalikan adalah suatu triple (IN, OUT, ERR) dengan semua anggota dari daftar yang asli yang kini tersedia bagi I/O. Jika timeout itu terlewati sebelum file-file yang manapun menjadi siap, suatu triple dari tiga list kosong dikembalikan. Jika tidak ada timeout ditetapkan lalu fungsi itu boleh menghalangi dengan tak terbatas.

Contoh-contoh :

Contoh-contoh ini kebanyakan UNIX-specific, seperti para pemakai Windows berharap akan melewati di depan.

Fcntl

Definisi-definisi yang berikut menunjukkan bagaimana fungsi fcntl dapat digunakan untuk mengubah suatu tanda file's "tidak blok". Ini bermanfaat, misalnya, jika kita ingin membaca dari masukan yang standar atau suatu pipa tetapi tidak ingin menghalangi sampai masukan tersedia. Sebagai gantinya, mempunyai himpunan tanda yang tidak blok, operasi masukan akan gagal dengan segera jika tidak ada masukan yang terbaca sekarang.

/* menset dan membersihkan tanda O_NONBLOCK dari suatu file */ set_nonblock FD:Int = fcntl FD F_SETFL (FLAGS or O_NONBLOCK)

where FLAGS = fcntl FD F_GETFL ();

clr_nonblock FD:Int = fcntl FD F_SETFL (FLAGS and not O_NONBLOCK) where FLAGS = fcntl FD F_GETFL ();

Dan di sini bagaimana kita dapat melaksanakan penguncian laporan di satu file secara menyeluruh.

/* tempat satu kunci membaca atau menulis laporan di satu file secara menyeluruh (gagal jika terjadi kesalahan) */

rdlock FD:Int = () where () = fcntl FD F_SETLK (F_RDLCK, 0, 0); /* melepaskan kunci dari file */

unlock FD:Int = () where () = fcntl FD F_SETLK (F_UNLCK, 0, 0); /* predikat untuk memeriksa apakah suatu kunci membaca atau menulis bisa ditempatkan */

rdlockp FD:Int = (LOCK!0 = F_UNLCK) where LOCK:Tuple =

fcntl FD F_GETLK (F_RDLCK, 0, 0); wrlockp FD:Int = (LOCK!0 = F_UNLCK)

where LOCK:Tuple =

fcntl FD F_GETLK (F_WRLCK, 0, 0);

Catatan bahwa untuk menerapkan fungsi-fungsi ini ke file object yang standar, anda dapat menggunakan fungsi fileno (lihat Extended File Functions) sebagai berikut:

==> rdlock (fileno F)

Select

fungsi Memilih menerima kedua files dan file descriptors ketika masukan. Di sini ada suatu cara untuk menguji apakah masukan sekarang ini tersedia dari suatu file/descriptor:

avail F = not null (select ([F],[],[],0)!0);

Ini bermanfaat, khususnya, jika file itu sebenarnya suatu pipa. Sebagai contoh:

==> def F = popen "sleep 5; echo done" "r"

==> avail F // tidak ada masukan yang terbaca, menunggu ... false

==> avail F // ...masukan yang tersedia sekarang true

==> fget F "done\n"

Bagaimanapun, kebanyakan dari waktu memilih digunakan untuk operasi multipleks I/O. Sebagai contoh, proses-proses pengulangan yang berikut masuk dari satu set dari file, satu garis pada waktu yang sama:

loop FILES = loop (proc FILES F)

where ([F|_],_,_) = select (FILES,[],[]) if not null FILES;

= () otherwise;

proc FILES F = // diselesaikan dengan file ini, membersihkannya filter (neq F) FILES

if feof F;

= // memproses satu baris writes (fgets F) || FILES;

Anonymous Pipes

Operasi Pipe dan dup2 menyediakan suatu cara yang cepat untuk menugaskan kembali masukan dan keluaran dari suatu proses anak dan menyambungnya kepada file object yang sesuai di dalam induk. Sebagai contoh, di sini bagaimana kita dapat menerapkan suatu fungsi popen2

yang bekerja seperti rutinitas popen yang terikut, tetapi mengizinkan untuk mengalihkan jurusan masukan dan keluaran dari suatu proses anak:

/* buat dua pipa yang tak dikenal, satu untuk induk untuk membaca dan anak itu untuk menulis, satu yang lainnya untuk anak untuk membaca dan induk untuk menulis. */

popen2 CMD = spawn2 CMD (P_IN, P_OUT) (C_IN, C_OUT)

where (P_IN, C_OUT) = pipe, (C_IN, P_OUT) = pipe;

/* mencabang anak dan mengalihkan arah stream masukan dan keluaran yang standar kepada tujuan anak dari pipa. Ini tercapai dengan dup2 SRC DEST yang menutup file descriptor DEST dan lalu membuat suatu salinan DEST dari SRC. Di dalam induk kita menggunakan fdopen untuk membuka dua file object yang baru untuk tujuan dari pipa-pipa induk itu. */

spawn2 CMD (P_IN, P_OUT) (C_IN, C_OUT)

= close P_IN || close P_OUT ||

dup2 C_IN (fileno INPUT) || dup2 C_OUT (fileno OUTPUT) || exec "/bin/sh" ["/bin/sh", "-c", CMD]

if fork = 0;

= close C_IN || close C_OUT ||

(fdopen P_IN "r", fdopen P_OUT "w") otherwise;

Fungsi popen2 mempekerjakan fork dan exec untuk menghasilkan suatu proses anak yang melaksanakan perintah yang diberi menggunakan shell, setelah pengalihan jurusan masukan dan keluaran anak untuk dua pipa. Di dalam proses induk, fungsi popen2 mengembalikan sepasang file-file yang dibuka pada tujuan lain dari descriptors anak.

Sebagai kelanjutan potongan dari kode Q menunjukkan bagaimana menerapkan fungsi popen2 yang digambarkan di atas untuk menyalurkan suatu daftar string lewat pipa ke dalam program pengurutan UNIX dan membangun daftar yang disortir dari keluaran:

mysort STRL = do (fprintf OUT "%s\n") STRL || fclose OUT || digest IN where (IN, OUT) = popen2 "sort";

digest IN = [] if feof IN;

= [freads IN|digest IN] otherwise;

Contoh:

==> mysort ["five","strings","to","be","sorted"] ["be","five","sorted","strings","to"]

==> wait // get exit code of child process (sort program) (15804,0)

Dalam dokumen Buku bhs pemrograman Q Equational 2018 (Halaman 182-187)