C中的输入输出系统调用创建,打开,关闭,读取,写入

重要术语
什么是文件描述符?
文件描述符是整数, 用于唯一标识进程的打开文件。
文件描述符表:文件描述符表是整数数组索引的集合, 这些整数数组索引是文件描述符, 其中元素是指向文件表条目的指针。操作系统中为每个进程提供了一个唯一的文件描述符表。
文件表条目:文件表条目是打开文件的内存中代理结构, 该文件在处理请求打开文件时创建, 并且这些条目保持文件位置。

C中的输入输出系统调用创建,打开,关闭,读取,写入

文章图片
标准文件描述符:任何进程启动时, 该进程文件描述符表的fd(文件描述符)会自动打开0、1、2(默认情况下)这3个fd引用文件表条目中的每个文件/ dev / tty
/ dev / tty
【C中的输入输出系统调用创建,打开,关闭,读取,写入】:终端的内存中替代
终奌站
:组合键盘/视频屏幕
C中的输入输出系统调用创建,打开,关闭,读取,写入

文章图片
从标准输入读取=> 从fd读取0
:每当我们从键盘上输入任何字符时, 它都会通过fd 0从stdin读取并保存到名为/ dev / tty的文件中。
写入stdout => 写入fd 1
:每当我们看到视频屏幕上的任何输出时, 它都来自名为/ dev / tty的文件, 并通过fd 1写入屏幕中的stdout。
写入stderr => 写入fd 2
:我们看到视频屏幕出现任何错误, 这也是通过fd 2从该文件写入屏幕中的stderr的结果。
I / O系统调用
基本上共有5种类型的I / O系统调用:
创造:
用于创建一个新的空文件。
Syntax in C language: int creat(char *filename, mode_t mode)

参数
filename:你要创建的文件的名称
mode:表示新文件的权限。
返回值:
返回第一个未使用的文件描述符(通常在进程中首次创建时使用3, 因为保留了0、1、2 fd)
错误时返回-1
在OS中如何运作
在磁盘上创建新的空文件
创建文件表条目
设置第一个未使用的文件描述符以指向文件表条目
使用的返回文件描述符, 失败时为-1
打开
:用于打开文件以进行读取, 写入或两者同时进行。
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_CREAT:创建文件(如果不存在), O_EXCL:如果已经存在则阻止创建
在OS中的运作方式
在磁盘上查找现有文件
创建文件表条目
设置第一个未使用的文件描述符以指向文件表条目
使用的返回文件描述符, 失败时为-1
// 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\n" , errno ); // print program detail "Success or failure" perror ( "Program" ); } return 0; }

输出如下:
fd = 3

关:
告诉操作系统你已经完成了文件描述符, 然后关闭fd指向的文件。
Syntax in C language#include < fcntl.h> int close(int fd);

参数
fd:文件描述符
返回
成功时为0。
-1表示错误。
它在操作系统中的工作方式
销毁文件描述符表的元素fd引用的文件表条目
–只要没有其他过程指向它!
将文件描述符表的元素fd设置为NULL
// 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\n" , fd1); // Using close system Call if (close(fd1) < 0) { perror ( "c1" ); exit (1); } printf ( "closed the fd.\n" ); }

输出如下:
opened the fd = 3closed the fd.

// 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\n" , fd2); exit (0); }

输出如下:
fd2 = 3

在这里, 在此代码中, 首先open()返回3因为当创建主进程时, 然后fd0、1、2已经被标准输入, 标准输出和斯特德。所以第一个未使用的文件描述符是3在文件描述符表中。之后在close()系统调用中释放了它3文件描述符, 然后设置3文件描述符为null。因此, 当我们调用第二个open()时, 第一个未使用的fd也是3。因此, 该程序的输出为3.
读:
从文件描述符fd指示的文件中, read()函数将cnt字节的输入读取到buf指示的存储区中。成功的read()将更新文件的访问时间。
Syntax in C language size_t read (int fd, void* buf, size_t cnt);

参数
fd:文件描述符
buf:从中读取数据的缓冲区
cnt:缓冲区的长度
返回:实际读取了多少字节
返回成功读取的字节数
到达文件末尾时返回0
错误返回-1
信号中断返回-1
重要事项
由于溢出, buf需要指向长度不小于指定大小的有效内存位置。
fd应该是从open()返回的有效文件描述符, 以执行读取操作, 因为如果fd为NULL, 则读取应生成错误。
cnt是请求的读取字节数, 而返回值是实际读取的字节数。同样, 有时读取系统调用读取的字节数应少于cnt。
// 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 byteswere read.\n" , fd, sz); c[sz] = '\0' ; printf ( "Those bytes are as follows: % s\n" , c); }

输出如下:
called read(3, c, 10).returned that 10 byteswere read.Those bytes are as follows: 0 0 0 foo.

假设foobar.txt由6个ASCII字符" foobar"组成。那么以下程序的输出是什么?
// 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\n" , c); exit (0); }

输出如下:
c = f

描述符fd1和fd2每个描述符都有自己的打开文件表条目, 因此每个描述符都有自己的文件位置foob??ar.txt。因此, 从fd2读取的第一个字节foob??ar.txt, 输出为c = f, 不是c = o.
写:
将buf中的cnt字节写入与fd相关的文件或套接字。 cnt不应大于INT_MAX(在limits.h头文件中定义)。如果cnt为零, 则write()仅返回0, 而不会尝试任何其他操作。
#include < fcntl.h> size_t write (int fd, void* buf, size_t cnt);

参数
fd:文件描述符
buf:将数据写入的缓冲区
cnt:缓冲区的长度
返回:实际写入了多少字节
返回成功写入的字节数
到达文件末尾时返回0
错误返回-1
信号中断返回-1
重要事项
需要打开文件进行写操作
buf的长度必须至少等于cnt所指定的长度, 因为如果buf的大小小于cnt, 则buf会导致溢出。
cnt是请求写入的字节数, 而返回值是实际写入的字节数。当fd要写入的字节数少于cnt时, 会发生这种情况。
如果write()被信号中断, 则结果是以下之一:
-如果write()尚未写入任何数据, 则返回-1并将errno设置为EINTR。
-如果write()已成功写入某些数据, 则它将返回其在中断之前写入的字节数。
// 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\n" , strlen ( "hello geeks\n" )); printf ( "called write(% d, \"hello geeks\\n\", %d)." " It returned %d\n" , fd, strlen ( "hello geeks\n" ), sz); close(fd); }

输出如下:
called write(3, "hello geeks\n", 12).it returned 11

在这里, 运行代码后, 如果在文件foo.txt中看到"你好极客"。如果foo.txt文件中已经包含一些内容, 则写入系统调用将覆盖该内容, 并且所有先前的内容已删除而且只有"你好极客内容将存在于文件中。
从程序中打印" hello world", 而不使用任何printf或cout函数。
// 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阵列写入stdout并打印输出"你好, 世界"。
如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请写评论。

    推荐阅读