UNIX/Linux学习笔记(5)系统调用与文件
学习笔记(4)中介绍了环境变量和内存映射,其中分配内存的函数设计到了有关系统调用的知识,今天小编来谈一谈我对系统调用和文件的简单认识
系统调用
1)操作系统与系统调用:
操作系统的主要功能是管理硬件资源和为应用程序开发人员提供良好的环境来使应用程序具有更好的兼容性。为了达到这个目标,内核提供了一系列具备预定功能的多内核函数,通过一组称为系统调用的接口提供给用户
2)系统调用的流程:
接受应用程序的请求 → 将请求传递给内核 → 内核调用相应函数 → 返回结果
3)系统调用:
①UNIX/Linux 把系统调用都封装成了C函数的形式,但它们并不是标准C的一部分
②标准库中的函数绝大部分执行在用户态,但部分时间也需切换到内核态(进行了系统调用)
③我们所写的代码可以直接调用系统接口,进入内核态,例如brk、sbrk
④系统调用的功能代码存储在内存中,接口定义在C库中,通过系统中断的方式实现调用
文件
1)一切皆文件:
①在UNIX/Linux系统下,几乎所有资源都是文件形式提供
②操作系统将它的服务、功能、设备抽象成简单的文件,提供一套简单统一的访问接口,使得程序可以像访问磁盘上的文件一样访问串口、终端、打印机、网络
终端:也称终端设备,是计算机网络中处于网络最外围的设备,主要用于用户信息的输入已经处理结果的输出
③UNIX/Linux下几乎任何对象都可以当做特殊类型的文件,以文件的形式对其访问,例如目录文件、设备文件、普通文件
2)文件描述符:
①文件描述符是一个非负整数,表示一个打开的文件
②由系统调用open/creat/socket
返回
③为什么引入文件描述符:为什么不使用标准库中的文件指针呢?那是因为记录文件相关信息的结构体存储在内核当中,为了不暴露内核的地址,所以不能将文件结构体指针直接给用户操作。我们可以这样理解,在内核中存在着一个记录文件设备的表,一列是文件描述符且对应一列文件结构体指针,那么文件描述符就相当于数组的下标了
④内核中已经默认打开的三个文件描述符:0(stdin)、1(stdout)、2(stderr)
>stdout(标准输出设备)在默认情况下是行缓冲,它的输出会存放在一个buffer中,遇到换行符的时候才输出到屏幕;stderr(标准错误输出设别)是无缓冲的,会直接输出到屏幕。当转向标准输出至磁盘文件时,stdout输出至磁盘文件,stderr仍输出至屏幕
3)与文件相关的系统调用:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
①int open(const char* pathname, int flags)
功能:打开文件
pathname:文件的路径
flags:文件的权限
返回值:文件描述符(若小于0则表示文件打开失败)
②int open(const char* pathname, int flags, mode_t mode)
功能:打开文件
pathname:文件的路径
flags:文件的权限
mode:设置文件的权限(属主+属组+其它)
返回值:文件描述符(若小于0则表示文件打开失败)
③int close(int fd)
功能:关闭文件
fd:文件描述符
返回值:成功返回0,失败返回-1
④ssize_t read(int fd, void* buf, size_t count)
功能:从文件中读取数据到buf中
fd:文件描述符
buf:数据的存储位置
count:读取的字节数
返回值:成功读取的字节数
⑤ssize_t write(int fd, const void* buf, size_t count)
功能:把buf中的数据写入到文件中
fd:文件描述符
buf:要写入数据的内存首地址
count:写入的字节数
返回值:成功写入的字节数
⑥off_t lseek(int fd. off_t offset, int whence)
功能:设置文件指针的位置
offset:偏移值
whence:文件指针的初始位置(SEEK_SET、SEEK_CUR、SEEK_END)
返回值:文件指针的位置
⑦int dup(int oldfd)
功能:复制文件描述符
oldfd:被复制的文件描述符
返回值:操作系统会从未指定的文件描述符中选择一个返回
⑧int dup2(int oldfd, int newfd)
功能:复制指定的文件描述符,如果newfd已经被使用则先关闭再复制
oldfd:被复制的文件描述符
newfd:想要的文件描述符
dup2(fd,1),原本文件描述符1代表的是标准输出设备,现将1所对应的文件变成了fd所对应的文件,那么原本输出在屏幕上的操作将输出在文件fd中(因为向stdout输出的函数,并不知道它的背后是什么,只是因为原先它对应着屏幕,所以才显示在屏幕上)
总结
其实系统调用函数与标准库中的文件操作函数很是类似fwrite
fread
fseek
fopen
fclose
,如若也是萌新的你可以和我一起去对照着看一下,区分一下系统调用和标准库函数的区别,共勉!