Linux System Prorgramming
LINUX内核API完全参考手册.pdf
第1章 简介和主要概念
1.4 Linux 编程概念
1.4.1 文件和文件系统
1.4.2 普通文件
1.4.3 目录和链接
1.4.4 硬链接
1.4.5 符号链接
参考:linux中的硬链接和符号链接
1.4.6 特殊文件
1.4.7 文件系统和名字空间
1.4.8 进程
1.4.9 线程
1.4.10 进程体系
1.4.11 用户和组
1.4.12 权限
1.4.13 信号
1.4.14 进程间通讯
1.4.15 头文件
1.4.16 错误处理
第2 章文件I/O
2.1 打开文件
2.1.1 open() 系统调用
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open (const char *name, int flags);
int open (const char *name, int flags, mode_t mode);
flags 参数:
O_RDONLY:
O_WRONLY:
O_RDWR:
O_APPEND
O_ASYNC
O_CREAT
O_DIRECT
O_DIRECTORY
O_EXCL
O_LARGEFILE
O_NOCTTY
O_NOFOLLOW
O_NONBLOCK
O_SYNC
O_TRUNC
2.1.2 新文件所有者
System V:文件所有者的用户id就是创建该文件的进程的有效用户id,
文件所有组id就是创建该文件的进程的组id
BSD ??:文件所有者的用户id就是创建该文件的进程的有效用户id,
文件所有组id就是上级目录的组ID
2.1.3 新文件权限
S IRWXU
S IRUSR
S IWUSR
S IXUSR
S IRWXG
S IRGRP
S IWGRP
S IXGRP
S IRWXO
S IROTH
S IWOTH
S IXOTH
最终写入磁盘的权限还需要mode参数用户文件创建的掩码(即umask)做按位与操作后来确定。
2.1.4 creat() 函数
2.2 用read() 读取文件
#include <unistd.h>
ssize_t read (int fd, void *buf, size_t len);
2.2.1 返回值
调用返回一个等于len的值。所有len个数读取字节存储在buf中,结果和预期的一致。
调用返回了一个大于零小于len的值,读取的字节存在buf中。:
出现信号量打断读取过程,或者读取过程中发生一个错误;或者在读取len个字节前已经抵达EOF,再次读取(更新buf和len的值)将读入剩余字节到buf的剩余字节到buf的剩余空间。或者指出问题发生的原因
调用返回0,标志着EOF,没有读入数据
调用返回-1,errno=EINTER,表示在读入字节前收到一个信号量,可以重新进行调用。
调用返回-1,errno=EAGAIN,读取因为没有可以用的数据而阻塞。而读请求应该在之后重新开启。这种只是在非阻塞模式下发生。
调用返回-1,errno!=EAGAIN&&errno!errno=EINTER,发生严重错误。
2.2.3 非阻塞读
不希望没有刻度数据时read()调用阻塞,而是调用立即返回-1,设置errno=EAGAIN。称非阻塞读
2.3 用write() 来写
#include <unistd.h>
ssize_t write (int fd, const void *buf, size_t
count);
2.4 同步I/O
2.4.1 fsync() 和fdatasync()
#include <unistd.h>
int fsync (int fd);
#include <unistd.h>
int fdatasync (int fd);
这两个调用都不保证任何更新的包含该文件的目录项同步到磁盘中,这就意味着如果文件链接刚刚被改过,文件数据可能会成功的写入磁盘,但是没有关联到相应的目录项上,致使文件不可以访问,为了保证目录项也同步到磁盘中,所以对目录项也的调用fsync();
2.4.3 sync()
#include <unistd.h>
void sync (void);
确保所以的缓冲去的(数据和元数据)都写入到磁盘中。
2.4.4 O_SYNC 标志
fsync() 和fdatasync()的系统开销比O_SYNC少。
2.4.5 O_DSYNC 和O_RSYNC
O_DSYNC:每次写操作时隐性的调用fdatasync()
O_RSYNC:读请求像谢请求那样进行同步.
2.5 直接I/O
2.6 关闭文件
#include <unistd.h>
int close (int fd);
2.6.1 错误码
2.7 用lseek() 查找
#include <sys/types.h>
#include <unistd.h>
off_t lseek (int fd, off_t pos, int origin);
origin:
1:SEEK_CUR,
2:SEEK_END,
3:SEEK_SET.
2.8 定位读写
1)pread()
#define _XOPEN_SOURCE 500
#include <unistd.h>
ssize_t pread (int fd, void *buf, size_t count,
off_t pos);
2)pwrite()
#define _XOPEN_SOURCE 500
#include <unistd.h>
ssize_t pwrite (int fd, const void *buf, size_t
count, off_t pos);
2.9 截短文件
#include <unistd.h>
#include <sys/types.h>
int ftruncate (int fd, off_t len);
和?
#include <unistd.h>
#include <sys/types.h>
int truncate (const char *path, off_t len);
2.10 I/O 多路复用(监听不同的文件)
#解决文件未准备好,应用阻塞的问题.
2.10.1 select()
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select (int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);
:在指定的文件描述符准备I/O前或者超过一定的时间限制,select()调用就会阻塞.
FD_CLR(int fd, fd_set *set);集合中移除一个文件描述符
FD_ISSET(int fd, fd_set *set);测试一个文件描述符是否在指定的集合中.
FD_SET(int fd, fd_set *set);集合中增加一个文件描述符.
FD_ZERO(fd_set *set);集合中移除所有文件描述符
*readfds:监测readfds集合中的文件描述符,确定是否有可读的数据
*writefds:监测writefds集合中的文件描述符,确定是否有一个写操作可以不阻塞的完成.
*exceptfds:监测exceptfds集合中的文件描述符,确定其中是否出现异常或者出现带外数据.
n:等于所有文件描述符的最大值加1.
timeout:指timeval结构体的指针:
#include <sys/time.h>
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
timeout是null,即使此时没有文件描述符处于I/0就绪状态,select也在tv_sec和tv_usec后返回.
2.10.2.3 pselect()
#define _XOPEN_SOURCE 600
#include <sys/select.h>
int pselect (int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,const struct timespec *timeout,const sigset_t *sigmask);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
sigmask:以此来解决信号和等待文件描述符之间的竞争条件.假如一个信号处理程序设置了一个全局标记,进程在每次调用select前都要检查这个标记,现在,假如在检查标记和调用之间收到信号,应用可能阻塞,并不响应该信号,pselect()提供一组可以阻塞的信号,阻塞的信号直到解除阻塞才会被处理,一旦pselect()返回,内核就恢复旧的信号掩码.
2.10.3 poll()
#include <sys/poll.h>
int poll (struct pollfd *fds, unsigned int nfds,int timeout);
timeout:在任何I/O就绪前需要等待的时间的长度.负值表示永远等待,零表示调用立即返回列出所有的未准备号的I/O.
fds:指上pollfd结构体数组
#include <sys/poll.h>
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events to watch */
short revents; /* returned events witnessed */
};
events:字段是要监视的文件描述符时间的一组位掩码.用户设置这个字段.
revents:字段是发生在该文件描述符上的事件的位掩码.内核在返回时设置这个这个字段.
2.10.3.3 ppoll()
2.10.4 epoll()/event poll接口
epoll把监听和注册从实际监听中分离出来
4.2.1 创建一个新的epoll 实例
#include <sys/epoll.h>
int epoll_create (int size)
4.2.2 控制epoll
#include <sys/epoll.h>
int epoll_ctl (int epfd, int op, int fd, struct
epoll_event *event);
op值:EPOLL CTL ADD/EPOLL CTL DEL/EPOLL CTL MOD.
epoll_event结构体:
struct epoll_event {
__u32 events; /* events */
union {
void *ptr;
int fd;
__u32 u32;
__u64 u64;
} data;
};
1:events的有效集:EPOLLERR/EPOLLET/EPOLLHUP/EPOLLIN/EPOLLONESHOT/EPOLLOUT/EPOLLPRI
EPOLLET:在监听文件上开启边缘触发.
水平触发:在状态发生时触发.
边缘触发:状态改变时触发.
2:data由用户设置.
4.2.3 等待Epoll 事件
#include <sys/epoll.h>
int epoll_wait (int epfd, struct epoll_event
*events, int maxevents, int timeout);
2.11 内核内幕
2.11.1 虚拟文件系统
2.11.2 页缓存
2.11.3 页回写
第3章缓冲输入输出/流
3.2 打开文件
#include <stdio.h>
FILE* fopen(const char * path, const char * mode);
3.2.2 通过文件描述符打开文件
#include <stdio.h>
FILE * fdopen (int fd, const char *mode);
3.3 关闭流
#include <stdio.h>
int fclose (FILE *stream);
3.3.1 关闭所有的流
#define _GNU_SOURCE
#include <stdio.h>
int fcloseall (void);
3.4从流中读取数据
3.4.1 单字节读取
#include <stdio.h>
int fgetc (FILE *stream);
3.4.2 把字符回放入流中
#include <stdio.h>
int ungetc (int c, FILE *stream);
3.4.3 按行的读取
#include <stdio.h>
char * fgets (char *str, int size, FILE *stream)
3.4.5 读取