一、主函数的参数和输出缓冲区
1、主函数的原型:
Int main(int argc,char *argv[], char *envp[]);
argc:参数个数
argv[]:参数列表;argv[0]是启动这个进程的命令;
envp[]:环境变量;
printf:将数据输出到内存中的缓冲区中,应该要满足一下四个条件,才会将缓冲区中的数据显示到界面上:
(1)\n
(2)程序结束—— exit(0);//进程结束时会刷新缓冲区
_exit(0);//不会刷新缓冲区,直接结束进程;
(3)缓冲区满
(4) 程序中调用函数:fflush(stdout);//主动刷新
二、文件操作函数
(1)库函数:fopen、fread、fwrite、fclose、fseek
FILE *fopen(char *file, char *flag);
(2)系统调用函数:open、read、write、close、lseek、stat
Int open(char *file, int flag,/*int mode*/);
Flag: O_RDONLY 只读打开
O_RDWR 读写打开
O_WRONLY 只写打开
O_CREAT 若此文件不存在,就创建它
O_APPEND 每次写时都追加到文件的尾端
O_TRUNC 如果此文件存在,而且为只写或读写成功打开,则将其长度截短为0
Mode:新建文件权限
Int read(int fd, void *buff, int size);//size:一次最多读多少字节;
返回值:-1 操作出错
>0 返回读到的字节数
Int write(int fd,void* buff, int size);
buff:要写入到文件中的数据的起始位置;
size:写入的个数,数据的长度
int close(int fd);//关闭文件描述符
int lseek(int fd, int count, int flag);//移动读写偏移量
count:移动的字节数
flag:移动的起始位置
三个位置:SEEK_SET SEEK_CUR SEEK_EMD
三个stat函数获取文件的属性信息:
Int stat(char *path, struct stat*st);
Int fstat(int fd, struct stst *st);
Int lstat(char *path, struct stst *st);
扫描目录:
Opendir readdir telldir closedir seekdir
(3)库函数和系统调用函数两者的关系和区别
库函数:库函数在函数库文件中实现,执行时只需要在用户态执行就可以了。库函数的调用在用户态,逻辑实现也是在用户态。
系统调用函数:操作系统内核抛出来给用户空间调用的接口,系统调用函数由用户态调用,在内核态执行。
库函数有可能还需要转调系统调用函数,比如foen,printf等。也有可能不需要转调系统调用函数,比如strlen,strcpy等。
(4)系统调用函数的实现原理以及用户态切内核态流程时
①以open函数为例;假设其系统调用号为如图所示:
②用户态切内核态流程
系统调用函数出发0x80中断,并且将系统调用号存储在eax寄存器中,然后陷入内核,内核开始执行中断处理程序,在系统调用表中查找系统调用号对应的系统内核函数并且调用,执行完成后又将返回值通过eax寄存器传递回用户空间。
注意:
由于fork函数创建的子进程的PCB是拷贝父进程的,并且这块是浅拷贝,所以父子进程会共享父进程fork之前打开的所有文件描述符。
(5)进程PCB中记录打开的文件资源的结构实现
PCB:struct file *filp[20];//fd是gilp的下标
Struct file: count:句柄数 文件描述符数 计数器
Pos:读写偏移量
Struct m_inode *m_inode:指向的结构体中包含文件的属性信息
Block:9 0~6 是直接映射
7 是间接映射
8 双重间接映射