1.I/O多路转接
/*********************************************
包含头文件: #include
函数原型: int select(int maxfdpl,fd_set *restrict readfds,
fd_set *restrict writefds,fd_set *restrict exceptfds,struct timeval *restrict tvptr);
函数说明:关心特定文件符是否可读,可写,有异常,tvptr表示愿意 等待多长时间
若tvptr为NULL 表示永久等待 (若指定条件的一个描述 符已经准备好或者捕捉到一个信号.select返回)
若tvptr→tv_sec == 0 && tvptr→tv_usec == 0,则根本不等
待
若tvptr→tv_sec != 0 || tvptr→tv_usec != 0,则等待特定时间
(可如(1)中断);
返回值:准备就绪的描述符数目,若超时,返回0,若出错,返回-1
**********************************************/
/**********************************************
包含头文件: #include
函数原型: int FD_ISSET(int fd,fd_set *fdset);
返回值: 若fd在描述符集中,返回非0值,否则,返回0
void FD_CLR(int fd,fd_set* fdset);
void FD_SET(int fd,fd_set *fdset);
void FD_ZERO(int fd,fd_set *fdset);
函数说明:意同名
**********************************************/
/***************************
包含头文件: #include <sys/select.h>
函数原型: int pselect(int maxfdpl,fd_set *restrict readfds, fd_set *restrict writefds,fd_set *restrict exceptfds,
const struct timespec * restrict tsptr,const sigset_t *restrict sigmask);
函数说明:可以在函数返回前屏蔽一些信号,超时控制更为精确,返回后恢复调用前屏蔽字,其他与select相同
返回值:准备就绪的文件描述符,若超时,返回0,若出错,返回-1
*******************************************/
/*****************************************
包含头文件: #include <poll.h>
函数原型: int poll(struct pollfd fdarray[],nfds_t nfds,int timeout);
参数说明:
struct pollfd
{
int fd; //文件描述符
short events; //请求的事件
short revents; //返回的事件
};
poll函数的事件标志符值
常量
说明
POLLIN
普通或优先级带数据可读
POLLRDNORM
普通数据可读
POLLRDBAND
优先级带数据可读
POLLPRI
高优先级数据可读
POLLOUT
普通数据可写
POLLWRNORM
普通数据可写
POLLWRBAND
优先级带数据可写
POLLERR
发生错误
POLLHUP
发生挂起
POLLNVAL
描述字不是一个打开的文件
后三个写入revent
当描述符被挂起(POLLHUP)就不能再写该描述符,但可能从该描述符读取数据
timeout指定我们要等待的时间:
timeout == -1 永远等待(准备好或捕捉到信号返回)
timeout == 0 不等待(测试所有描述符并返回)
timeout > 0 等待timeout毫秒(准备好或捕捉到信号返回)
*****************************************/
存储映射
/*****************************************
包含头文件: #include <sys/uio.h>
函数原型: ssize_t readv(int fd,const struct iovec* iov,int iovent);
ssize_t writev(int fd,const struct iovec *
iov,int iovent);
函数说明:
struct iovec
{
void *iov_base; //缓冲区开始地址
size_t iov_len; //缓冲区大小
};
iov是指向struct iovec数组的一个指针,iovent是元素个数
使用iov[0]…...iov[iovent – 1]非连续缓冲区进行I/O
返回值:已读或已写的字节数,若出错,返回-1
*****************************************/
/*****************************************
包含头文件: #include <sys/mman.h>
函数原型: void* mmap(void* addr,size_t len,int prot,int flag,int fd,off_t off);
函数说明:
addr参数用于指定映射存储区的起始地址,通常将其设置为0,这表示由系统分配该映射区的地址
fd参数指定要被映射文件的描述符,在文件映射到地址空间前,必须打开文件
len指定要映射的字节数
off是要映射字节在文件中的起始偏移量
prot参数指定映射存储区的保护要求:
Prot 说明
PROT_READ 映射区可读
PROT_WRITE 映射区可写
PROT_EXEC 映射区可执行
PROT_NONE 映射区不可访问
flag参数影响映射存储区的多种属性:
MAP_FIXED 返回值必须等于attr(获得最大可移植性,将attr设为0)
MAP_SHARED 修改映射区即修改源文件
MAP_PRIVATE 映射区文件的副本,修改不会影响源文件
*****************************************/
/*****************************************
包含头文件: #include <sys/mman.h>
函数原型: int mprotect(void* addr,size_t len,int prot);
函数说明:更改映射区的权限
返回值:若成功,返回0,若出错,返回-1
*****************************************/
/*****************************************
包含头文件: #include <sys/mman.h>
函数原型: int msync(void* addr,size_t len,int flags);
函数说明:将映射区修改的内容冲洗到文件里
flags指定为MS_SYNC时等待冲洗完毕函数才返回
flags指定为MS_ASYNC时只是发出冲洗请求便返回
*****************************************/
/*****************************************
包含头文件: #include <sys/mman.h>
函数原型: int munmap(void* addr,size_t len);
函数说明:解除文件与存储映射区的关系
只有终止进程时或使用该函数才能解除文件与存储映射区的关系
关闭文件描述符无影响
返回值:若成,返回0,若出错,返回-1
*****************************************/
异步I/O
/*****************************************
struct aiocb
{
int aio_fildes; /*文件描述符*/
off_t aio_offset; /*I/O时文件偏移量*/
volatile void* aio_buf; /*I/O时使用缓冲区
size_t aio_nbytes;/*转移字节数*/
int aio_reqprio; /*属性*/
struct sigevent aio_sigevent; /*信号消息*/
int aio_lio_opcode;
/*I/O操作: LIO_READ(交给aio_read处理)
LIO_WRITE(交给aio_write处理)
LIO_NOP(被忽略的空操作)*/
};
struct sigevent
{
int sigev_notify; /*通知类型*/
int sigev_signo; /*信号*/
union sigval sigev_value; /*通知参数*/
void (*sigev_notify_function)(union sigval)
/*通知函数*/
pthread_attr_t *sigev_notify_attributes;
/*通知属性*/
};
sigev_notify字段控制通知类型:
SIGEV_NONE 异步I/O完成后,不通知进程
SIGEV_SIGNAL 异步I/O完成后,产生sigev_signo信号
SIGEV_THREAD 当异步I/O请求完成时,由sigev_notify_function字段指定的函数被调用
*****************************************/
/****************************************
包含头文件: #include <aio.h>
函数原型 int aio_read(struct aiocb *aiocb);
int aio_write(strcut aiocb *aiocb);
函数说明:得到异步I/O请求,放入等待队列(返回结果与实际IO并无关系)
返回值:若成功,返回0,若出错,返回-1
****************************************/
/****************************************
包含头文件: #include <aio.h>
函数原型: int aio_fsync(int op,struct aiocb* aiocb);
函数说明:op设为 O_DSYNC 请求刷新文件内容
op设为O_SYNC 等待刷新文件内容返回
****************************************/
/****************************************
包含头文件: #include <aio.h>
函数原型: int aio_error(const struct *aiocb aiocb);
函数说明: 获取异步I/O同步操作的完成状态
返回值:
0 异步操作完成
-1 aio_error调用失败具体进errno
EINPROCESS 异步I/O操作还在等待
其它情况 异步操作失败返回的错误码
****************************************/
/*****************************************
包含头文件: #include <aio.h>
函数原型:ssize_t aio_return(const struct aiocb *aiocb);
函数说明:如果异步操作完成,通过aio_return获取异步
操作的返回值
返回值:如果aio_return本身失败,返回-1,其他情况返回异步操作的返回值
*****************************************/
/*****************************************
包含头文件: #include <aio.h>
函数原型: int aio_suspend(const struct aiocb *const list[],int nent,const struct timespec *timeout);
函数说明:如果所有事务都完成,通过aio_suspend阻塞进程直到特定异步I/O完成
*****************************************/
/*****************************************
包含头文件: #include <aio.h>
函数原型: int aio_cancel(int fd,struct aiocb* aiocb);
函数说明:fd参数指定未完成的异步I/O操作文件描述符,若acb为NULL,系统将会尝试取消所有该文件上未完成的异步I/O操作
返回值:
AIO_ALLDONE 所有操作在尝试取消它们之前已完成
AIO_CANCELED 所有要求的操作都被取消
AIO_NOTCANCELED 至少有一个要求的操作没被取消
*****************************************/
/*****************************************
包含头文件: #include <aio.h>
函数原型: int lio_listio(int mode,struct aiocb *restrict const list[restrict],int nent,struct sigevent *restrict sigev);
函数说明:mode参数决定I/O是否异步
LIO_WAIT 非异步
LIO_NOWAIT 异步
对列表进行I/O操作,sigev是所有I/O操作完成后的通知
*****************************************/
管道:
/*****************************************
包含头文件: #include <unistd.h>
函数原型: int pipe(int fd[2]);
函数说明:创建管道,fd[0]为读打开,fd[1]为写打开
返回值:若成功,返回0,若出错,返回-1
*****************************************/
vi 15.1.c
#include
#include
#include
#include
#define MAXLINE 5
int main()
{
int fd[2];
volatile int n;
char buf[MAXLINE];
if (pipe(fd) < 0)
{
printf("pipe error\n");
exit(1);
}
pid_t pid;
if ((pid = fork()) < 0)
{
printf("fork error\n");
exit(0);
}
else if (pid == 0)
{
close(fd[1]);
n = read(fd[0],buf,n);
write(STDOUT_FILENO,buf,n);
exit(0);
}
else
{
close(fd[0]);
n = read(STDIN_FILENO,buf,MAXLINE);
write(fd[1],buf,n);
}
return 0;
}
vi mywait.h
#include
static int fd1[2],fd2[2];
void TELL_WAIT()
{
if (pipe(fd1) < 0 || pipe(fd2) < 0)
{
printf("pipe error\n");
exit(1);
}
}
void WAIT_CHILD()
{
char c;
if (read(fd1[0],&c,1) != 1)
{
printf("read error\n");
exit(1);
}
}
void TELL_CHILD()
{
if (write(fd2[1],"c",1) < 0)
{
printf("write error\n");
exit(1);
}
}
void WAIT_PARENT()
{
char c;
if (read(fd2[0],&c,1) < 0)
{
printf("read error\n");
exit(1);
}
}
void TELL_PARENT()
{
if (write(fd1[1],"p",1) < 0)
{
printf("write error\n");
exit(1);
}
}
vi 15.2.c
#include
#include
#include "pipewait.h"
#include
int main()
{
pid_t pid;
TELL_WAIT();
if ((pid = fork()) < 0)
{
printf("fork error\n");
}
else if (pid == 0)
{
WAIT_PARENT();
printf("son is second\n");
exit(0);
}
else
{
printf("father is first\n");
TELL_CHILD();
if (waitpid(pid,NULL,0) < 0)
{
printf("waitpid error\n");
exit(0);
}
exit(0);
}
return 0;
FIFO
/*****************************************
包含头文件: #include <sys/stat.h>
函数原型: int mkfifo(const char* path,mode_t mode);
int mkfifoat(int fd,const char* path,mode_t mode);
函数说明:创建一个命名管道(FIFO),FIFO是一种文件类型
返回值:若成功,返回0,若出错,返回-1
*****************************************/
IPC
/*****************************************
包含头文件: #include <sys/ipc.h>
函数原型: key_t ftok(const char* path,int id);
函数说明:由一个路径名和项目ID产生一个键
返回值:若成功,返回键,若出错,返回key_t - 1
*****************************************/
/*****************************************
strcut ipc_perm
{
uid_t uid; /*用户有效用户ID*/
gid_t gid; /*用户有效组ID*/
uid_t cuid; /*创建者的有效用户ID*/
gid_t cgid; /*创建者的有效组ID*/
mode_t mode; /*权限模式*/
...
}
*****************************************/
/****************************************
共享存储:共享存储允许两个或多个进程共享一个给定
的存储区,因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种IPC
****************************************/
/*****************************************
共享存储:
struct shmid_ds
{
strcut ipc_perm shm_perm; /*ipc 结构*/
size_t shm_segsz;; /*共享段大小*/
pid_t shm_lpid; /*上次调用shmop()的进程ID*/
pid_t shm_cpid; /* 创建者的进程ID*/
shmatt_t shm_nattch; /*连接(共享)数量*/
time_t shm_atime; /*上次连接时间*/
time_t shm_dtime; /*上次分离时间*/
time_t shm_ctime; /*上次改变时间*/
};
*****************************************/
/*****************************************
包含头文件: #include <sys/shm.h>
函数原型:int shmget(key_t key,size_t size,int flag);
函数说明:获得共享存储标识符
返回值:若成功,返回共享存储ID,若出错,返回-1
*****************************************/
/****************************************
包含头文件: #include <sys/shm.h>
函数原型:int shmctl(int shmid,int cmd,struct shmid_ds *buf);
函数说明:
cmd指定运作方式:
IPC_STAT 取此段的shmid_ds结构,并存储于buf
IPC_SET 按buf结构的值指定shm_perm.uid,shm_perm.gid shm_perm.mode
(此命令执行需要相应权限)
IPC_PMID 从系统中删除该共享存储段
****************************************/
/****************************************
包含头文件: #include <sys/shm.h>
函数原型: void* shmat(int shmid,const void* addr,int flag);
函数说明:一旦创建了一个共享存储段,进程就可调用shmat将其连接到它的地址空间(addr一般指定为0)
如果在flag中指定了SHM_RDONLY位,则以只读
方式连接此段,否则以读写方式连接此段
返回值:若成功,返回指向共享存储段的指针,若出错,返回-1
****************************************/
/*****************************************
包含头文件: #include <sys/shm.h>
函数原型: int shmdt(const void* addr);
函数说明:若成功,shmdt将使相关shmid_ds结构中的
shm_nattch减一
*****************************************/
/*****************************************
POSIX 信号量
包含头文件: #include <semaphore.h>
函数原型: sem_t * sem_open(const char* name,int oflag,…../*mode_t mode);
函数说明:创建一个信号量或引用一个现有信号量
当引用一个现有信号量可以将oflag设定为0
当想得到一个新的信号量可将oflag设定O_CREAT
若设定为O_CREAT | O_EXCL,若信号量已存在,则sem_open调用失败
返回值:若成功,返回信号量,若出错,返回SEM_FAILED
*****************************************/
/*****************************************
包含头文件: #include <semaphore.h>
函数原型: int sem_close(sem_t *sem);
函数说明: 释放任何信号量相关的资源
返回值:若成功,返回0,若出错,返回-1
*****************************************/
/*****************************************
包含头文件: #include <semaphore.h>
函数原型:int sem_unlink(const char* name);
函数说明:删除信号量的名字,如果没有打开信号量的引用,则该信号量会被销毁,否则,销毁延迟到最后一个打开的引用关闭
返回值:若成功,返回0,否则,返回-1
*****************************************/
/*****************************************
包含头文件: #include <semaphore.h>
函数原型: int sem_trywait(sem_t *sem);
int sem_wait(sem_t *sem);
函数说明:使用sem_wait时,信号量计数是0,就会发生阻塞,直到成功使信号量减一或者被信号中断时才返回
若使用sem_trywait,信号量计数为0,则返回-1并将
errno置为EAGAIN
*****************************************/
/*****************************************
包含头文件: #include <semaphore.h>
#include
函数原型:sem_timewait(sem_t *restrict sem,const struct timespec *restrict tsptr);
函数说明:若信号量为0,选择阻塞一段确定的时间
返回值:若成功,返回0,若出错,返回-1
*****************************************/
/*****************************************
包含头文件: #include <semaphore.h>
函数原型: int sem_post(sem_t *sem);
函数说明:将信号量值增加一
返回值:若成功,返回0,若出错,返回-1
*****************************************/