重要术语
什么是文件描述符? 文件描述符是唯一标识进程的打开文件的整数。
文件描述符表 :File descriptor table是整数数组索引的集合,这些索引是文件描述符,其中的元素是指向文件表项的指针。操作系统中为每个进程提供了一个唯一的文件描述符表。
文件表条目: 文件表条目是内存中打开文件的代理结构,在进程请求打开文件时创建,这些条目保持文件位置。
标准文件描述符 :当任何进程启动时,该进程文件描述符表的fd(文件描述符)0、1、2将自动打开(默认情况下),这3个fd中的每一个都引用名为 /开发/运输及运输署
/开发/运输及运输署 :内存中的终端代理 航空站 :组合键盘/视频屏幕
从标准输入读取=>从fd 0读取 :无论何时我们从键盘写入任何字符,它都会通过fd 0从stdin读取,并保存到名为/dev/tty的文件中。 写入标准输出=>写入fd 1 :每当我们看到任何输出到视频屏幕时,它都来自名为/dev/tty的文件,并通过fd 1写入屏幕中的标准输出。 写入标准=>写入fd 2 :我们在视频屏幕上看到任何错误,这也是通过fd 2将文件写入屏幕中的stderr。
I/O系统调用
基本上共有5种类型的I/O系统调用:
1.创建: 用于创建新的空文件。
Syntax in C language: int create(char *filename, mode_t mode)
参数:
- 文件名: 要创建的文件的名称
- 模式: 指示新文件的权限。
返回:
- 返回第一个未使用的文件描述符(第一次创建时通常为3,因为0、1、2 fd是保留的)
- 错误时返回-1
它在操作系统中的工作原理
- 在磁盘上创建新的空文件
- 创建文件表条目
- 将第一个未使用的文件描述符设置为指向文件表条目
- 返回使用的文件描述符失败时为-1
2.打开 :用于打开文件进行读取、写入或同时进行读取和写入。
Syntax in C language #include<sys/types.h> #include<sys/stat.h> #include <fcntl.h> int open (const char* Path, int flags [, int mode ]);
参数
- 路径: 要使用的文件的路径
- 当您不在文件的同一目录中工作时,请使用以“/”开头的绝对路径。
- 当您在文件的同一目录中工作时,请使用相对路径,它是唯一具有扩展名的文件名。
- 旗帜: 你喜欢用什么
- O_RDONLY :只读, O_WRONLY :只写, O_RDWR :读和写, O_创造 :创建不存在的文件, 不包括 :如果已存在,则阻止创建
它在操作系统中的工作原理
- 在磁盘上查找现有文件
- 创建文件表条目
- 将第一个未使用的文件描述符设置为指向文件表条目
- 返回使用的文件描述符失败时为-1
C
// C program to illustrate // open system call #include<stdio.h> #include<fcntl.h> #include<errno.h> extern int errno ; int main() { // if file does not have in directory // then file foo.txt is created. int fd = open( "foo.txt" , O_RDONLY | O_CREAT); printf ( "fd = %d/n" , fd); if (fd ==-1) { // print which type of error have in a code printf ( "Error Number % d" , errno ); // print program detail "Success or failure" perror ( "Program" ); } return 0; } |
输出:
fd = 3
3.关闭: 告诉操作系统您已使用文件描述符并关闭fd指向的文件。
Syntax in C language #include <fcntl.h> int close(int fd);
参数:
- fd: 文件描述符
返回:
- 0 关于成功。
- -1 错误。
它在操作系统中的工作原理
- 销毁文件描述符表的元素fd引用的文件表条目 –只要没有其他流程指向它!
- 将文件描述符表的元素fd设置为 无效的
C
// C program to illustrate close system Call #include<stdio.h> #include <fcntl.h> int main() { int fd1 = open( "foo.txt" , O_RDONLY); if (fd1 < 0) { perror ( "c1" ); exit (1); } printf ( "opened the fd = % d" , fd1); // Using close system Call if (close(fd1) < 0) { perror ( "c1" ); exit (1); } printf ( "closed the fd." ); } |
输出:
opened the fd = 3 closed the fd.
C
// C program to illustrate close system Call #include<stdio.h> #include<fcntl.h> int main() { // assume that foo.txt is already created int fd1 = open( "foo.txt" , O_RDONLY, 0); close(fd1); // assume that baz.tzt is already created int fd2 = open( "baz.txt" , O_RDONLY, 0); printf ( "fd2 = % d" , fd2); exit (0); } |
输出:
fd2 = 3
这里,在这段代码中,first open()返回 3. 因为当主进程创建时 0, 1, 2 他们已经被绑架了 斯特丁 , 斯特杜特 和 标准错误 .所以第一个未使用的文件描述符是 3. 在文件描述符表中。在此之后,in close()系统调用将于本周释放 3. 文件描述符,然后在设置 3. 文件描述符为 无效的 .所以当我们调用second open()时,第一个未使用的fd也是 3. .所以,这个程序的输出是 3. .
4.阅读: 从文件描述符fd指示的文件中,read()函数将输入的cnt字节读取到buf指示的内存区域中。成功读取()会更新文件的访问时间。
Syntax in C language size_t read (int fd, void* buf, size_t cnt);
参数:
- fd: 文件描述符
- 缓冲器: 从中读取数据的缓冲区
- cnt: 缓冲区长度
返回:实际读取了多少字节
- 返回成功读取的字节数
- 到达文件末尾时返回0
- 错误时返回-1
- 信号中断时返回-1
要点
- 缓冲器 由于溢出,需要指向长度不小于指定大小的有效内存位置。
- fd 应该是从open()返回的有效文件描述符,以执行读取操作,因为如果fd为NULL,则读取将生成错误。
- 碳纳米管 是请求读取的字节数,而返回值是实际读取的字节数。此外,有时读取系统调用读取的字节数应该少于cnt。
C
// C program to illustrate // read system Call #include<stdio.h> #include <fcntl.h> int main() { int fd, sz; char *c = ( char *) calloc (100, sizeof ( char )); fd = open( "foo.txt" , O_RDONLY); if (fd < 0) { perror ( "r1" ); exit (1); } sz = read(fd, c, 10); printf ( "called read(% d, c, 10). returned that" " %d bytes were read." , fd, sz); c[sz] = ' ' ; printf ( "Those bytes are as follows: % s" , c); } |
输出:
called read(3, c, 10). returned that 10 bytes were read. Those bytes are as follows: 0 0 0 foo.
假设是福巴。txt由6个ASCII字符“foobar”组成。那么以下程序的输出是什么?
C
// C program to illustrate // read system Call #include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<stdlib.h> int main() { char c; int fd1 = open( "sample.txt" , O_RDONLY, 0); int fd2 = open( "sample.txt" , O_RDONLY, 0); read(fd1, &c, 1); read(fd2, &c, 1); printf ( "c = %c" , c); exit (0); } |
输出:
c = f
描述符 fd1 和 fd2 每个描述符都有自己的打开文件表条目,因此每个描述符都有自己的文件位置 福巴。txt .因此,从 fd2 读取数据的第一个字节 福巴。txt ,输出为 c=f 不 c=o .
5.写下: 将cnt字节从buf写入与fd关联的文件或套接字。cnt不应大于INT_MAX(在limits.h头文件中定义)。如果cnt为零,write()只返回0,而不尝试任何其他操作。
#include <fcntl.h> size_t write (int fd, void* buf, size_t cnt);
参数:
- fd: 文件描述符
- 缓冲器: 将数据写入的缓冲区
- cnt: 缓冲区长度
返回:实际写入了多少字节
- 返回成功写入的字节数
- 到达文件末尾时返回0
- 错误时返回-1
- 信号中断时返回-1
要点
- 需要打开文件进行写操作
- 缓冲器 需要至少与cnt指定的长度相同,因为如果buf大小小于cnt,则buf将导致溢出情况。
- 碳纳米管 是请求写入的字节数,而返回值是实际写入的字节数。当 fd 要写入的字节数少于cnt。
- 如果write()被信号中断,则效果如下: -如果write()尚未写入任何数据,则返回-1并将errno设置为EINTR。 -如果write()成功写入了一些数据,它将返回中断前写入的字节数。
C
// C program to illustrate // write system Call #include<stdio.h> #include <fcntl.h> main() { int sz; int fd = open( "foo.txt" , O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) { perror ( "r1" ); exit (1); } sz = write(fd, "hello geeks" , strlen ( "hello geeks" )); printf ( "called write(% d, "hello geeks\n", %d)." " It returned %d" , fd, strlen ( "hello geeks" ), sz); close(fd); } |
输出:
called write(3, "hello geeks", 12). it returned 11
在这里,当你看到文件foo。运行代码后,你会得到一个“ 你好,极客们 “。如果foo.txt文件中已经有一些内容,则写系统调用覆盖这些内容,并删除所有以前的内容。” 删除 而且只有“ 你好,极客们 “内容将包含在文件中。
从程序中打印“hello world”,而不使用任何printf或cout函数。
C
// C program to illustrate // I/O system Calls #include<stdio.h> #include<string.h> #include<unistd.h> #include<fcntl.h> int main ( void ) { int fd[2]; char buf1[12] = "hello world" ; char buf2[12]; // assume foobar.txt is already created fd[0] = open( "foobar.txt" , O_RDWR); fd[1] = open( "foobar.txt" , O_RDWR); write(fd[0], buf1, strlen (buf1)); write(1, buf2, read(fd[1], buf2, 12)); close(fd[0]); close(fd[1]); return 0; } |
输出:
hello world
在这段代码中,buf1数组的字符串 “你好,世界” 首先写入stdin fd[0],然后将该字符串写入stdin到buf2数组。在此之后,将buf2数组写入标准输出并打印输出“ 你好,世界 “. 本文由 卡丹·帕特尔 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。