系统调用:#man 2 #就是系统调用函数由操作系统实现并提供给外部应用程序的额编程接口(API,application programming interface)。是应用程序同系统之间数据交互的桥梁。linux中真正存在的函数并不和man 2中的系统函数名一致。我们能看到的系统调用(man 2中的)函数是linux内核函数的浅封装。如下图:
我们接下来学习的函数严格上叫系统函数(系统调用浅封装),
只有这些函数可以驱动内核,
C语言的fputc等函数实际底层是这些系统函数的又封装。注意:虽然系统函数直接调用内核,但因为缓冲区(详见下图和表)的存在当 单字节 用read、write时没有库函数fopen、fputc拷贝快。内核会有一个4096的缓冲区。用于预读入和缓输出。使用问题:因为种种潜在的问题,例如上面的缓存问题,一般我们编程还是使用库函数,而不是直接使用系统函数。但具体的还是看场景需要。
区别 | 系统函数 | 库函数 |
---|---|---|
缓存 | 无用户级缓冲区 | 有用户级缓冲区 |
写入内核方式 | 直接与内核对接 | 自身缓冲区满时才将数据推给内核 |
作用:打开或创建文件。man 2 open //get more information
//在vim命令模式下,光标至于按K直接进入man帮助中
1.function model#include
4.常见错误详见man 2 openDEMO:链接地址:git@github.com:Panor520/LinuxCode.git中LinuxCode/systemfunctions/open.c文件。
作用:关闭文件描述符。man 2 close
//在vim命令模式下,光标至于按K直接进入man帮助中1.function model#include
man 2 read
//在vim命令模式下,光标至于按K直接进入man帮助中1.NAME:read - read from a file descriptor2.SYNOPSIS#include
man 2 write
//在vim命令模式下,光标至于按K直接进入man帮助中1.NAMEwrite - write to a file descriptor2.SYNOPSIS#include
man 2 fcntl
#
#直接修改已打开文件描述符的flags(O_RDONLY, O_WRONLY等)。
1.NAMEfcntl - manipulate file descriptor2.SYNOPSIS#include
DEMO:链接地址:git@github.com:Panor520/LinuxCode.git中LinuxCode/systemfunctions/fcntl.c文件。
man 2 lseek
1.NAMElseek - reposition read/write file offset2.SYNOPSIS#include
4.RETURN VALUEerror : -1success : 较起始位置偏移量
5.应用场景1)对同一文件描述符的“读”、“写”,使用的是同一偏移量.DEMO:链接地址:git@github.com:Panor520/LinuxCode.git中LinuxCode/systemfunctions/lseek.c文件。2)使用lseek获取文件大小,DEMO:链接地址:git@github.com:Panor520/LinuxCode.git中LinuxCode/systemfunctions/lseek_getfilesize.c文件。3)使用lseek拓展文件大小,要想让实际大小变为拓展后的大小必须要进行一次I\O操作。DEMO:链接地址:git@github.com:Panor520/LinuxCode.git中LinuxCode/systemfunctions/lseek_expendfilesize.c文件。//拓展:函数truncate 直接拓展文件大小。 详情 man 2 truncate
man 2 stat //有example1.NAMEstat - get file status
2.SYNOPSISint stat(const char *pathname, struct stat *statbuf);
3.parameterpathname:路径statbuf:结构体struct statstruct stat {dev_t st_dev; /* ID of device containing file */ino_t st_ino; /* Inode number */mode_t st_mode; /* File type and mode */nlink_t st_nlink; /* Number of hard links */uid_t st_uid; /* User ID of owner */gid_t st_gid; /* Group ID of owner */dev_t st_rdev; /* Device ID (if special file) */off_t st_size; /* Total size, in bytes */blksize_t st_blksize; /* Block size for filesystem I/O */blkcnt_t st_blocks; /* Number of 512B blocks allocated *//* Since Linux 2.6, the kernel supports nanosecondprecision for the following timestamp fields.For the details before Linux 2.6, see NOTES. */struct timespec st_atim; /* Time of last access */struct timespec st_mtim; /* Time of last modification */struct timespec st_ctim; /* Time of last status change */#define st_atime st_atim.tv_sec /* Backward compatibility */#define st_mtime st_mtim.tv_sec#define st_ctime st_ctim.tv_sec};
4.RETURN VALUEOn success, zero is returned. On error, -1 is returned, and errno is set appropriately.
5.应用1)获取文件大小statbuf.st_size2)获取文件类型st_mode使用宏函数判断文件类型,statbuf.st_mode。穿透符号链接:stat:会。lstat:不会例子:一个软连接,stat会直接获取软连接的原始文件,而lstat获取的是软连接自身。3)获取文件权限statbuf.st_mode.
文件由两字节构成,位图如下:
man 2 access //用法看这个
1.NAMEaccess, faccessat - check user's permissions for a file2.SYNOPSIS#include
man 2 chmod //查看详情1.NAMEchmod, fchmod, fchmodat - change permissions of a file2.SYNOPSIS#include
man 2 truncate //1.NAMEtruncate, ftruncate - truncate a file to a specified length2.SYNOPSIS#include
man 2 link //1.NAMElink, linkat - make a new name for a file就是创建文件硬链接。2.SYNOPSIS#include
man 2 unlink 1.NAMEunlink, unlinkat - delete a name and possibly the file it refers to就是删除硬链接,如果硬链接数为1,那就是删除文件.2.SYNOPSIS#include
3.应用调用此函数后,只是让文件具备了被释放的条件,具体释放时机要等到所有打开该文件的进程关闭该文件,再由系统内部调度算法决定释放时间。也就是说unlink可以用来删除正在使用的文件。
man 2 readlink
读取符号链接文件本身。
man 2 rename
重命名文件
man 2 getcwd
相当于 pwd
man 2 chdir
相当于 cd
man 3 opendir //库函数
打开目录文件
1.NAMEopendir, fdopendir - open a directory2.SYNOPSIS#include
3.RETURN VALUEThe opendir() and fdopendir() functions return a pointer to the directory stream. On error, NULL is returned, and errno is set appropriately.
man 3 closedir //库函数
1.NAMEclosedir - close a directory2.SYNOPSIS#include
3.RETURN VALUEThe closedir() function returns 0 on success. On error, -1 is returned, and errno is set appropriately.
man 3 readdir //库函数1.NAMEreaddir - read a directory每次读一个目录项。要全部读出来要循环。
2.SYNOPSIS#include
3.parameter
struct dirent {ino_t d_ino; /* Inode number */off_t d_off; /* Not an offset; see below */unsigned short d_reclen; /* Length of this record */unsigned char d_type; /* Type of file; not supportedby all filesystem types */char d_name[256]; /* Null-terminated filename */};
4.RETURN VALUEOn success, readdir() returns a pointer to a dirent structure.
5.应用可以用来实现ls的功能。DEMO实现ls -R功能:链接地址:git@github.com:Panor520/LinuxCode.git中LinuxCode/systemfunctions/myls_R.c文件。
man 2 dup2dup
dup2(fd1,fd2); //把给fd2的操作重定向给fd1上,//例如给fd2执行write(fd2,"1234",4);那么数据1234会写到fd1上 fcntl也可以实现重定向。
PCB进程控制块实际是一个结构体,
其中有一个成员为文件描述符指针,指向文件描述符表。
文件描述符表:键值对映射存放文件描述符,操作系统只暴露键,对值隐藏。键为整数(也就是我们写代码时获取的整数)。值对应一个指向文件结构体(struct file {})的指针。结构体中的信息就是一系列文件属性、IO缓冲区等信息。struct file {...文件偏移量,文件访问权限,文件打开标志,文件内核缓冲区的首地址;struct operations * f op;...};
文件描述符:内核默认有三个:标准输入 0 STDIN_FILENO标准输出 1 STDOUT_FILENO标准错误 2 STDERR_FILENO.当我们使用系统函数新增时,总是从整数3开始。依次增加,最大为1024(最大值可修改).(新打开文件描述符遵循最小可用整数规则)
阻塞和非阻塞是文件的特性(属性)。产生阻塞场景:1)读设备文件(/dev/) 。 终端(Terminal)文件:/dev/tty .也就是终端的读写都是用的这个文件(默认是以阻塞状态打开的)。可以从新以非阻塞装填打开该文件进行输入输出。(详见下面Demo)阻塞是一直持续等待输入,否则不输出。非阻塞就是等两秒看有没有输入,有的话输入,没有的话歇会再看。最优解:你有输入时就告诉我,然后我输出。(这样效率最高)2)读网络文件。(读常规文件无阻塞概念)DEMO:利用系统输入输出文件/dev/tty,去实现非阻塞输入输出,链接地址:git@github.com:Panor520/LinuxCode.git中LinuxCode/systemfunctions/tty.c文件。