讲内核之前,先讲讲系统调用。因为用户是通过系统调用才能访问系统内核。
操作系统提供用户程序调用的一组’特殊’的接口。就是内核提供给用户可以操作内核的一组函数接口。
用户程序可以通过这组“特别”接口来获得操作系统内核提供的服务,比如用户可以通过文件系统相关的调用请求系统打开、关闭或读写文件、可以通过时钟相关的系统调用获取系统时间或设置定时器等。用户借助系统调用操作内核。从逻辑上来说,系统调用可被看成一个内核与用户空间程序交互的接口。
将linux的运行空间分为内核空间与用户空间,他们各自运行在不同的级别中,逻辑上相互隔离。所以进程也分内核进程和用户进程,但很多情况用户进程需要获得系统服务(调用系统程序),这就需要系统提供“特殊接口” 。用户态可以通过软件中断切换到内核态
linux下对文件操作有两种方式:系统调用(system call)和库函数调用(library functions)。
库函数
库函数调用 是第三方的函数接口。
系统调用 是内核提供给用户的函数接口。
库函数调用也可以使用 系统调用。
使用系统调用必须花费时间。
提高工作效率方法:文件操作时,先存在缓存区,再一次性库函数调用。
Linux一切设备皆文件。可以系统调用I/O函数,对文件进行操作(常见open()、close()、write()、read()等)。
打开文件或新建文件时,系统会返回一个文件描述符,文件描述符用来指定存在的文件。文件描述符是非负整数,是文件的标识。
系统会为每一个进程 分配文件描述符表。管理进程所有文件描述符。
系统会为每一个进程 ,默认打开三个文件描述符:0,1,2
文件描述符 | 意义 | 代表函数 |
---|---|---|
0 | 标准输入设备(键盘) | scanf |
1 | 标准输出设备(终端) | printf |
2 | 标准错误输出(终端) | perror |
文件描述符表 是通过“位图”来管理文件描述符。使用1024位2进制管理。每一位二进制值的 1代表打开,0代表关闭。
查看当前进程号
命令:ps -A | grep “当前进程执行文件”
查看当前系统文件的文件描述符数量
命令:ulimit -a
修改当前系统文件的描述符数量
命令:ulimit -n 2048
文件常见操作IO:open、close、write、read
#include
#include
#include
int open(const char*pathname,int flags); //flags 打开文件操作权限
int open(const char*pathname,int flags,.mode_t mode); //mode 打开不存在文件,并创建,设置在磁盘上的权限。
功能:打开文件,若存在并可以选择创建。
参数:
pathname:文件路径和文件名
flags:打开文件标识,
必选项:O_RDONLY.O_WRONLY,O_RDWR
可选项:
取值 | 含义 |
---|---|
O_CREAT | 文件不存在则创建文件,使用此选项时需使用mode说明文件的权限 |
O_EXCL | 如果同时指定O_CREAT,且文件已经存在,则出错 |
O_TRUNC | 如果文件存在,则清空文件内容 |
O_ARREND | 写文件时,数据添加到文件末尾 |
O_NONBLOCK | 对于设备文件,以O_NONBLOCK方式打开可以做非阻塞I/O |
mode:这个参数,只有在文件不存在时有效,指新建文件时指定文件的磁盘权限
返回值:
成功:返回打开文件描述符
失败:-1
mode_t:是整型类型 int
mode文件在磁盘的用户权限
磁盘文件的用户权限分类:所有拥有者权限(u)、同组用户权限(g)
其他用户权限(o)
mode系统掩码umask:
shell进程的umask掩码可以用umask命令查看
umask:查看掩码(补码) //系统去掉的权限,为了保护系统文件
文件最终权限=给定的文件权限 - umask
#include
声明:int close(int fd);
参数fd:文件描述符,open函数的返回值
返回值:
成功:0
失败:-1,并设置**errno**(系统全局变量)
colse工作步骤,先将文件描述符的数量-1。相反open是将描述符数量+1.当文件描述符数量变成0时,系统回收文件描述符所占的内核空间。
#include
ssize_t write(int fd,const void *buf,size_t conut);
功能:把指定的数据写入文件(fd)
参数:
fd:文件描述符
buf:数据首地址
count:写入数据的长度(字节)
返回值:
成功:实际写入数据的字节格式
失败:-1(文件没有写权限时,会返回-1)
#实例
#include
#include
#include
#include
#include
#include
int main(int argc,char const *argv[])
{
int fd = open("a.txt",O_WRONLY | O_CREAT, 0666); //打开一个权限为666的a.txt文件,没有就创建
if(fd<0)
{
perror("open");
return 0;
}
printf("fd = %d\n",fd);
char buf[128]=""; //数据缓冲区
fgets(buf,sizeof(buf),stdin); //等待键盘输入数据到缓冲区
buf[strlen(buf)-1]=0; //remote '\n'
write(fd,buf,strlen(buf));
close(fd);
return 0;
}
#include
ssize_t read(int fd,void *buf,size_t conut);
功能:把指定文件数据读到内存(缓冲区)
参数:
fd:文件描述符
buf:内存首地址
count:读取的字节个数
返回值:
成功:实际读取到的字节个数
失败:-1(文件权限不够、文件已经关闭或没有打开)