操作系统的核心部分是一组对系统硬件进行控制的底层接口(设备驱动文件),访问设备或者文件的底层函数会出现用户态和核心态之间的切换,为了提高运行效率,我们应该减少对系统的调用。本文首先对用户需要减少系统调用的原因进行说明,然后对系统调用的API进行简单的介绍。
一、为什么系统调用应该尽量减少为什么系统调用需要尽可能的减少调用?
- 系统调用会影响性能
- 硬件的读写限制
系统调用的时间比函数调用更加耗费时间。很多程序开始时运行于用户态,但在执行的过程中,一些操作需要在内核权限下才能执行,这就涉及到一个从用户态切换到内核态的过程[1],系统调用完成,从内核态切换回用户态。如何做才能减少系统调用效率?答案是提高单次读写大小,具体大小取决于设备本身。为了解决这个问题,Linux在满足设备数据块长度要求的情况下将对设备的操作封装成了标准IO库(stdio.h),它合理地降低了系统调用开销。
二、操作系统内核提供对设备、文件的访问操作系统的核心部分是一组对系统硬件进行控制的底层接口(设备驱动文件),访问设备或者文件的底层函数有:
- open 打开文件或设备
- read 读取文件或设备
- write 写入文件或设备
- close 关闭文件或设备
- ioctl 文件或设备特有功能设置
用户可以通过系统提供的底层函数对一个已经挂载在系统中的设备进行操作。(开读写关和特殊操作)
2.1 open#include //一般来说只要这个
#include //不符合POSIX规范需要加上
#include //不符合POSIX规范需要加上
int open(const char * path, int oflags);
int open(const char * path, int oflags, mode_t mode)
可以看出,open()系统调用既可打开文件,亦可创建文件。文件描述符是我们标识特定文件的方法,其他系统调用都将会使用这个标识符。
参数说明:
- const char * path 文件路径
- int oflags 打开方式
- mode_t 访问权限
oflags含义:
oflags含义O_RDONLY只读O_WRONLY只写O_RDWR可读可写返回值说明:
打开成功返回文件描述符,失败返回-1并设置全局变量error。在实际使用中,程序会自动打开三个文件描述符:
自动打开的描述符:
自动打开的描述符含义0标准输入1标准输出2标准错误因为返回的文件描述符总是从最小的开始,而0 1 2 已经被占用,故一般返回3。
2.2 write#include
size_t write(int fd,const void * buf,size_t nbytes);
参数说明
- int fd 已经打开的文件描述符
- const void * buf 缓冲区首地址
- size_t nbytes 期望写入的字节数
返回值说明
如果一切顺利,返回值等于期望写入的字节数;若文件描述符错误返回-1,;若设备对数据块有大小限制,返回实际写入的字节数
2.3 read#include
size_t read(int fd, void * buf, size_t nbytes);
参数说明
- int fd 已经打开的文件描述符
- void * buf 缓冲区首地址
- size_t nbytes 期望读入的字节数
返回值说明
一切顺利的情况下,返回值等于实际读入的字节数;如果读到文件尾,返回0;发生错误返回-1,并设置全局error
2.4 close#include
int close(int fd);
参数说明
- int fd 已经打开的文件描述符
返回值说明 成功调用返回0;调用失败返回-1。
2.5 ioctl#include
int ioctl(int fd,int cmd,...);
ioctl函数提供了控制设备、描述符行为和底层配置服务接口。
2.6 其他系统调用操纵描述符- lseek
- fstat/stat/lstat
- dup/dup2
管道多进程通信会用到dup/dups, 简单介绍一下dup/dups
#include
int dup(int oldfd);
int dup2(int oldfd, int newfd);
参数说明
- int oldfd 待复制的文件描述符
- int newfd 指定的新的文件描述符
返回值说明 返回一个新的文件描述符
实际上,调用dup(oldfd)等效于,fcntl(oldfd, F_DUPFD, 0) 而调用dup2(oldfd, newfd)等效于,close(oldfd);fcntl(oldfd, F_DUPFD, newfd);
【1】《Linux探秘之用户态与内核态》https://www.cnblogs.com/bakari/p/5520860.html 【1】《Linux程序设计(第四版)》第三章 文件操作 【2】 《linux之dup和dup2函数解析》https://blog.csdn.net/silent123go/article/details/71108501