简介几种系统调用函数:write、read、open、close、

  在 Linux 中,一切(或几乎一切)都是文件,因此,文件操作在 Linux 中是十分重要的,为此,Linux 系统直接提供了一些函数用于对文件和设备进行访问和控制,这些函数被称为系统调用(syscall),它们也是通向操作系统本身的接口。

一、系统调用

  系统调用就是 Linux 内核提供的一组用户进程与内核进行交互的接口。这些接口让应用程序受限的访问硬件设备,提供了创建新进程并与已有进程进行通信的机制,也提供了申请操作系统其他资源的能力。

  系统调用工作在内核态,实际上,系统调用是用户空间访问内核空间的唯一手段(除异常和陷入外,它们是内核唯一的合法入口)。系统调用的主要作用如下:

1)系统调用为用户空间提供了一种硬件的抽象接口,这样,当需要读写文件时,应用程序就可以不用管磁盘类型和介质,甚至不用去管文件所在的文件系统到底是哪种类型;

2)系统调用保证了系统的稳定和安全。作为硬件设备和应用程序之间的中间人,内核可以基于权限、用户类型和其他一些规则对需要进行的访问进行判断;

3)系统调用是实现多任务和虚拟内存的前提。

  要访问系统调用,通常通过 C 库中定义的函数调用来进行。它们通常都需要定义零个、一个或几个参数(输入),而且可能产生一些副作用(会使系统的状态发生某种变化)。系统调用还会通过一个 long 类型的返回值来表示成功或者错误。通常,用一个负的值来表明错误,0表示成功。系统调用出现错误时,C 库会把错误码写入 errno 全局变量,通过调用 perror() 库函数,可以把该变量翻译成用户可理解的错误字符串。

二、几种常用的系统调用函数

2.1 write 系统调用

  系统调用 write 的作用是把缓冲区 buf 的前 nbytes 个字节写入与文件描述符 fildes 关联的文件中。它返回实际写入的字节数。如果文件描述符有错或者底层的设备驱动程序对数据块长度比较敏感,该返回值可能会小于 nbytes。如果函数返回值为 0,就表示没有写入任何数据;如果返回值为 -1,则表明 write 系统调用出现了错误,错误代码保存在全局变量 errno 里。 write 系统调用的原型如下:

#include <unistd.h>

size_t write(int fildes,const void *buf,size_t nbytes);

  其中,size_t 是标准 C 库中定义的一个数据类型,实际上就是 unsigned int。

  fildes 是文件描述符,内核利用文件描述符来访问文件,它是一个非负的整数,当打开现存文件或者新建一个文件时,都会返回一个文件描述符。有多少文件描述符取决于系统的配置情况,当一个程序开始运行时,它一般有 3 个已经打开的文件描述符:标准输入 0;标准输出 1;标准错误 2。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
        size_t x = write(1,"my name is tongye!\n",20);
        printf("you have writed %d words to the buffer\n",x);

exit(0);
}

/* 输出结果:
my name is tongye!
you have writed 20 words to the buffer
*/

  这段代码简单演示了一下 write 系统调用函数的用法:从缓冲区 buffer 中读取前 20 个字节写入标准输出中,write 返回了实际写入的字节数。

2.2 read 系统调用

  系统调用 read 的作用是:从文件描述符 fildes 相关联的文件里读入 nbytes 个字节的数据,并把它们放到数据区 buf 中。它返回实际读入的字节数,这可能会小于请求的字节数。如果 read 调用返回 0,就表示没有读入任何数据,已到达了文件尾;如果返回 -1,则表示 read 调用出现了错误。read 系统调用的原型如下:

#include <unistd.h>

size_t read(int fildes,void *buf,size_t nbytes);

  用一段代码演示一下用法:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
        char buffer[30];
        size_t x = read(0,buffer,30);
        write(1,buffer,x);

exit(0);
}

/* 输出结果:
hello ,my name is tongye!
hello ,my name is tongye!
*/

  这段代码使用 read 系统调用函数从标准输入读取 30 个字节到缓冲区 buffer 中去(输出结果中的第一行是从标准输入键入的),然后使用 write 系统调用函数将 buffer 中的字节写到标准输出中去。

2.3 open 系统调用

  系统调用 open 用于创建一个新的文件描述符。

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int open(const char *path,int oflags);
int open(const char *path,int oflags,mode_t mode);  // oflags 标志为 O_CREAT 时,使用这种格式

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/e581b56db2f42ec9232f451ef8582f33.html