学习的课程在b站:史上最强最细腻的linux嵌入式C语言学习教程【李慧芹老师】
感谢李老师!感谢up主!
本篇博客只是收集一下学习过程中遇到的函数和其他知识点,并不会详细展开。某个函数的具体情况还需通过man手册来进一步了解。
一、I/O
1.1 标准I/O
- FILE结构体
- 文件的打开/关闭
fopen();
fclose();
命令ulimit -a
能显示系统的一些限制信息,比如一个进程默认最多打开1024个文件。 - 文件内容的读取/写入
fgetc();fputc();
fgets();fputs();
fread();fwrite(); - 函数族
printf();scanf() - 错误代码
全局变量errno
perror();输出errno代表的错误信息到stderr
strerror();将errno转换为错误代表的字符串 - 读取一行
getline(); - 文件指针定位函数,缓冲区刷新函数
fseek();ftell();rewind();fflush();
fseeko();ftello();
全缓冲:目标stream是文件时,是全缓冲。只有遇到一下三种情况之一时才会将缓冲区内容输出到目标stream中:缓冲区装满;调用fflush()主动刷新缓冲区;遇到\0
行缓冲:目标stream是stdout、stdin时,是行缓冲。只有遇到\n的时候,才会将缓存区内容输出到目标stream中。
无缓冲:目标是stderr时,是无缓冲。不会缓冲,内容会直接输出到目标stream中。
- 临时文件
tmpnam();tmpfile();
1.2 系统调用I/O
- 文件描述符
每个进程都有一个自己的数组,该进程打开的每个stream都会在这个数组中占有一格。对于文件而言,格子中保存了一个指向结构体的指针,而该结构体中又保存了指向该文件inode的指针,inode中保存了文件实际在物理内存中占用了哪些block。“文件描述符”就是某个文件在数组中对应的下标值,是一个int值。
进程开启时数组中默认前三个分别是stdin,stdout,stderr - 文件的打开/关闭
open();close(); - 文件内容的读取/写入,文件指针定位
read();write();lseek(); - 按规定长度截断文件
truncate(); - FILE结构体和文件描述符的转换
fileno();fdopen(); - 文件共享
打开同一个文件多次,得到多个指向同一个文件的文件描述符 - 重定向函数,原子操作
dup();dup2();
复制文件描述符,使用当前可用范围内最小的文件描述符作为复制得到的结果。两个文件描述符位置上的指针指向同一个结构体,这个结构体指向文件的inode。 - 操纵文件描述符,设备I/O控制
fcntl();ioctl();
1.3 高级IO
-
IO多路转接:select
监视文件描述符,如果发生感兴趣的变化就通知处理。
select(nfds,readfds,writefds,exceptfds,timeout);
以事件为单位组织文件描述符集合。比较古老,因此移植性较好。
阻塞地监视文件描述符,当发生变化时会修改readfds,writefds,exceptfds三个文件描述符集合,保留发生改变的,清除没改变的。 -
IO多路转接:poll
int poll(fds,nfds,timeout);
struct pollfd {
int fd; // file descriptor
short events; // requested events
short revents; // returned events
};
fds是结构体pollfd的数组起始地址,每个结构体包含一个文件描述符fd,感兴趣的事件event,revent保存实际发生的事件。poll以文件描述符为单位阻塞地等待事件发生。当某个文件描述符发生了指定的event时poll就会返回,并将发生的事情保存在revent中。 -
IO多路转接:epoll
Linux系统在poll的基础上进一步封装,因此没法移植到其他平台上。poll中的结构体数组在epoll中称为一个epoll file,由内核管理。用户无法直接操作结构体数组,只留出一些接口函数留给用户。
int epooll_create(int size); 创建一个epoll file。size和epoll中管理的文件描述符个数无关,Linux2.6.8以后就废弃了,只要随便给一个正数就行。返回值为epoll file的文件描述符。
int epoll_ctl(epfd,op,fd,event); 给fd添加、修改、删除的event。
int epoll_wait(epfd,events,maxevents,timeout); 从epfd中取最多maxevents个事件,保存在数组events中。
// epoll_wait()的man手册部分包含以下内容:
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
typedef union epoll_data { // 是一个共用体
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
- select poll epoll对比
图片源自另一个课程
- 其他读写函数
readv(); 读取一些碎片地址上的数据
writev(); 往一些碎片地址上写数据 - 存储映射IO
mmap();munmap(); 将一个文件的内容映射到当前进程的虚拟内存空间中,作为一块数据段来操作文件的内容。把原本利用文件描述符对文件的操作变成对当前进程的一块内存的操作。映射完成后可以close该文件,并不影响对映射过来的内存的操作。如果最后一个参数选择匿名映射MAP_ANONYMOUS,则可以不依赖于任何文件,而是将一块指定大小的实际内存空间映射到本进程的虚拟内存空间中。
mmap和malloc:mmap可以选择匿名映射而在自己的虚拟内存空间中开辟一块指定大小的空间,作用和malloc类似。而munmap和free类似用于释放一块虚拟内存空间。
利用mmap()可以完成父子进程间的共享内存通信。父进程先mmap匿名映射一块内存到自己的内存空间中,然后fork产生一个子进程,子进程的内存空间中也保留了这种映射关系。
- 文件锁
fcntl();
lockf();
flock();
文件锁作用在文件的inode上,因此通过某个fd给文件上的锁可以通过其他fd解锁。
二、文件系统
2.1 目录和文件
-
获取文件属性
stat();fstat();lstat(); -
文件访问权限
st_mode是一个16位的位图,用于表示文件类型、文件访问权限,以及特殊权限位 -
umask
防止产生权限过松的文件 -
文件权限的更改/管理
chmod、fchmod -
文件系统