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

重要术语

null

什么是文件描述符? 文件描述符是唯一标识进程的打开文件的整数。

文件描述符表 :File descriptor table是整数数组索引的集合,这些索引是文件描述符,其中的元素是指向文件表项的指针。操作系统中为每个进程提供了一个唯一的文件描述符表。

文件表条目: 文件表条目是内存中打开文件的代理结构,在进程请求打开文件时创建,这些条目保持文件位置。

图片[1]-C中的输入输出系统调用|创建、打开、关闭、读取、写入-yiteyi-C++库

标准文件描述符 :当任何进程启动时,该进程文件描述符表的fd(文件描述符)0、1、2将自动打开(默认情况下),这3个fd中的每一个都引用名为 /开发/运输及运输署

/开发/运输及运输署 :内存中的终端代理 航空站 :组合键盘/视频屏幕

图片[2]-C中的输入输出系统调用|创建、打开、关闭、读取、写入-yiteyi-C++库

从标准输入读取=>从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主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享