man的级别
1、系统命令
2、系统接口
3、函数库
4、特殊文件,比如设备文件
5、文件
6、游戏
7、系统的软件包
8、系统管理命令
9、内核
man 2 stat
open函数:
int open(char *pathname, int flags) #include <unistd.h>
参数:
pathname: 欲打开的文件路径名
flags:文件打开方式: #include <fcntl.h>
O_RDONLY|O_WRONLY|O_RDWR O_CREAT|O_APPEND|O_TRUNC|O_EXCL|O_NONBLOCK ....
返回值:
成功: 打开文件所得到对应的 文件描述符(整数)
失败: -1, 设置errno
int open(char *pathname, int flags, mode_t mode) 123 775
参数:
pathname: 欲打开的文件路径名
flags:文件打开方式: O_RDONLY|O_WRONLY|O_RDWR O_CREAT|O_APPEND|O_TRUNC|O_EXCL|O_NONBLOCK ....
mode: 参数3使用的前提, 参2指定了 O_CREAT。 取值8进制数,用来描述文件的 访问权限。 rwx 0664
创建文件最终权限 = mode & ~umask
返回值:
成功: 打开文件所得到对应的 文件描述符(整数)
失败: -1, 设置errno
close函数:
int close(int fd);
错误处理函数: 与 errno 相关。
printf("xxx error: %d\n", errno);
char *strerror(int errnum);
printf("xxx error: %s\n", strerror(errno));
void perror(const char *s);
perror("open error");
read函数:
ssize_t read(int fd, void *buf, size_t count);
参数:
fd:文件描述符
buf:存数据的缓冲区
count:缓冲区大小
返回值:
0:读到文件末尾。
成功; > 0 读到的字节数。
失败: -1, 设置 errno
-1: 并且 errno = EAGIN 或 EWOULDBLOCK, 说明不是read失败,而是read在以非阻塞方式读一个设备文件(网络文件),并且文件无数据。
write函数:
ssize_t write(int fd, const void *buf, size_t count);
参数:
fd:文件描述符
buf:待写出数据的缓冲区
count:数据大小
返回值:
成功; 写入的字节数。
失败: -1, 设置 errno
文件描述符:
PCB进程控制块:本质是结构体。
成员:文件描述符表。
文件描述符:0/1/2/3/4/.../1023 表中可用的最小的。
0 - STDIN_FILENO
1 - STDOUT_FILENO
2 - STDERR_FILENO
阻塞、非阻塞: 是设备文件、网络文件的属性。
产生阻塞的场景。 读设备文件。读网络文件。(读常规文件无阻塞概念。)
/dev/tty -- 终端文件。
open("/dev/tty", O_RDWR|O_NONBLOCK) --- 设置 /dev/tty 非阻塞状态。(默认为阻塞状态)
fcntl:获取或设置文件状态
int (int fd, int cmd, ...)
int flgs = fcntl(fd, F_GETFL);
flgs |= O_NONBLOCK
fcntl(fd, F_SETFL, flgs);
获取文件状态: F_GETFL
设置文件状态: F_SETFL
lseek函数:
off_t lseek(int fd, off_t offset, int whence);
参数:
fd:文件描述符
offset: 偏移量
whence:起始偏移位置: SEEK_SET/SEEK_CUR/SEEK_END
返回值:
成功:较起始位置偏移量
失败:-1 errno
应用场景:
1. 文件的“读”、“写”使用同一偏移位置。
2. 使用lseek获取文件大小
3. 使用lseek拓展文件大小:要想使文件大小真正拓展,必须引起IO操作。
使用 truncate 函数,直接拓展文件。 int ret = truncate("dict.cp", 250);
传入参数:
1. 指针作为函数参数。
2. 同常有const关键字修饰。
3. 指针指向有效区域, 在函数内部做读操作。
传出参数:
1. 指针作为函数参数。
2. 在函数调用之前,指针指向的空间可以无意义,但必须有效。
3. 在函数内部,做写操作。
4。函数调用结束后,充当函数返回值。
传入传出参数:
1. 指针作为函数参数。
2. 在函数调用之前,指针指向的空间有实际意义。
3. 在函数内部,先做读操作,后做写操作。
4. 函数调用结束后,充当函数返回值。
文件系统/文件存储:
inode:存储文件属性信息,本质为结构体。如:权限、类型、大小、时间、用户、盘块位置等,也叫文件属性管理结构,也叫i节点。
大多数inode都存储在磁盘上,少量常用和近期使用的inode会被缓存到内存里。
ls -l 会把inode结构体中的内容显示出来
dentry:目录项,本质为结构体,重要成员变量有:文件名、inode...,文件内容(data)保存在磁盘盘块中。
源文件的inode和它的硬链接inode,是一样的。创建硬链接,保留源文件的inode,文件名变了。
当没有inode指向磁盘盘块空间时,这个盘块将被覆盖。
stat/lstat 函数:获取文件属性,就是从 inode 结构体中读取
int stat(const char *path, struct stat *buf);
参数:
path: 文件路径
buf:(传出参数) 存放文件属性。
返回值:
成功: 0
失败: -1 errno
获取文件大小: buf.st_size
获取文件类型: buf.st_mode
获取文件权限: buf.st_mode
符号穿透:stat会。lstat不会。
link() 创建硬链接,ln命令就是调用了link函数
unlink() 删除一个文件的目录项,Linux删除文件的机制是,不断将st_nlink减1,直至减为0。
unlink函数删除文件时,如果文件的硬链接数为0,没有dentry对应,但该文件不会马上被释放,要等所有打开该文件的进程都关闭该文件,系统才会挑时间释放该文件
隐式回收:进程运行结束后,该进程打开的所有文件会被关闭,申请的内存会被释放,系统的这一特性被称为隐式回收系统资源。
目录操作函数:
DIR * opendir(char *name);
int closedir(DIR *dp);
struct dirent *readdir(DIR * dp);
struct dirent {
inode
char dname[256];
}
perror()
void perror(const char *s);
功能:将上一个函数发生错误的原因输出到标准设备(stderr)。
注:stdout 是标准输出文件,文件描述符为2
stderr 是标准错误输出文件,文件描述符为3
参数s所指的字符串会先打印出来,后面再加上错误原因字符串。
此错误原因依照全局变量errno的值来决定要输出的字符串。
在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。
当你调用"某些"函数出错时,该函数已经重新设置了errno的值。
perror函数只是将你输入的一些信息和现在的errno所对应的错误一起输出。
perror("stat error");
SIGCHLD,在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程
int pause(void); (系统调用)
返回值:-1 并设置errno为EINTR
阻塞当前进程,当前进程进入睡眠状态。直到有信号递达将其唤醒。该函数只有成功时返回值为-1,同时errno的值置为EINTR,失败没有返回值。
注意,只有当一个信号递达且处理方式被捕捉时,pause函数引起挂起操作的进程才会被唤醒,而且只有当信号处理完后(调用完用户处理函数),pause函数才返回-1,且errno置EINTR,进程被唤醒继续执行后面的程序。如果信号的处理方式为默认处理方式或者忽略(丢弃),那么pause函数不会返回值,且进程也不会被激活,而是一直阻塞(挂起)。
pause收到的信号不能被屏蔽,如果被屏蔽,那么pause就不能被唤醒。