Linux内核 系统调用和文件IO

系统调用(system calls)

讲内核之前,先讲讲系统调用。因为用户是通过系统调用才能访问系统内核

定义:

操作系统提供用户程序调用的一组’特殊’的接口。就是内核提供给用户可以操作内核的一组函数接口

作用:

用户程序可以通过这组“特别”接口来获得操作系统内核提供的服务,比如用户可以通过文件系统相关的调用请求系统打开、关闭或读写文件、可以通过时钟相关的系统调用获取系统时间或设置定时器等。用户借助系统调用操作内核。从逻辑上来说,系统调用可被看成一个内核与用户空间程序交互的接口。Linux内核 系统调用和文件IO_第1张图片

存在的意义 系统调用保护内核

将linux的运行空间分为内核空间与用户空间,他们各自运行在不同的级别中,逻辑上相互隔离。所以进程也分内核进程和用户进程,但很多情况用户进程需要获得系统服务(调用系统程序),这就需要系统提供“特殊接口” 。用户态可以通过软件中断切换到内核态

系统调用和库函数的区别

linux下对文件操作有两种方式:系统调用(system call)和库函数调用(library functions)。
库函数

  1. 不需要调用系统调用
  2. 需要调用系统调用

库函数调用 是第三方的函数接口。
系统调用 是内核提供给用户的函数接口。
库函数调用也可以使用 系统调用。

使用系统调用必须花费时间。

C库中IO函数工作流程

提高工作效率方法:文件操作时,先存在缓存区,再一次性库函数调用。
Linux内核 系统调用和文件IO_第2张图片

文件描述符(重要)和查看进程号

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操作

文件常见操作IO:open、close、write、read

打开文件open

  1. man 2 open 查看open函数
#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

close关闭文件标识符

#include 
声明:int close(int fd);
参数fd:文件描述符,open函数的返回值
返回值:
成功:0
失败:-1,并设置**errno**(系统全局变量)
colse工作步骤,先将文件描述符的数量-1。相反open是将描述符数量+1.当文件描述符数量变成0时,系统回收文件描述符所占的内核空间。

write向文件写函数

#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;
}

read 读取文件数据

#include 
ssize_t read(int fd,void *buf,size_t conut);
功能:把指定文件数据读到内存(缓冲区)
参数:
fd:文件描述符
buf:内存首地址
count:读取的字节个数
返回值:
成功:实际读取到的字节个数
失败:-1(文件权限不够、文件已经关闭或没有打开)

你可能感兴趣的:(Linux系统基础,linux,服务器,运维)