linux进程间通信
1. 管道。
匿名一次性使用的,半双工。一个进程往输出端写管道,另一个进程从输入端读管道。
int pipe(int fds[2]);
2. FIFO特别文件
有名管道,作为特别文件存储于文件系统中。有名管道一旦建立就存在于文件系统中,除非显示的unlink
3. 消息队列、信号量和共享内存
函数 msgget semget shmget msgctl semctl shmctl
每个ipc资源有两个唯一的标志与其相连 关键字和标识(关键字类似于文件名,标志类似于文件描述字用来访问资源的操作)
关键字获得函数 key_t ftok(const char* path, int id)
ipc_perm结构,当进程创建ipc资源时,内核存储了ipc资源的属主和组id和访问权限等信息。
uid_t uid 当前有效用户id
gid_t gid 当前有效组id
cuid_t cuid 创建用户id
cgid_t cgid 创建组id
mode_t mode 访问权限
ipc资源创建之后,可以长期存储在文件系统中,直到被删除或者系统重启。
shell命令:ipcs -q -s -m ipcrm
a. 消息队列
struct msqid_ds(消息队列相连的数据结构) {
struct ipc_perm msg_perm; 该消息队列的属主和访问权限
struct msg* msg_first; 指向第一个消息的指针
struct msg* msg_last; 指向最后一个消息的指针
msgqnum_t msg_qnum; 当前消息的个数
msglen_t msg_qytes; 最大容量字节数
pid_t msg_lspid; 最后一个调用msgsnd的进程
pid_t msg_lrpid; 最后一个调用msgrcv的进程
time_t msg_stime; 最后发送时间
time_t msg_rtime; 最后接收时间
time_t msg_ctime; 最后修改时间
}
struct msg {
struct msg* mas_next; 下个消息的指针
long msg_type; 消息的类型
caddr_t msg_sport; 消息正文地址
sort msg_ts; 消息正文的大小
}
int msgget(key_t key, int msgflg);
msgflg IPC_CREAT当系统不存在和key相连的消息队列时,就创建一个key为关键字的消息队列(用于创建一个新的队列)
IPC_EXCL 和IPC_CREAT一起使用时,当已经存在队列时,则返回失败(防止关键字重复)
int msgctl(int msgid, int cmd, struct msqid_ds* buf);
控制消息队列cmd
IPC_STAT 获得msgid的消息队列数据结果到buf中
IPC_SET 设置buf中ipc_perm为消息队列的新值
IPC_RMID 删除消息队列
int msgsnd(int msgid, const void* msg, size_t size, int msgflag);
ssize_t msgrcv(int msgid, void* msg, size_t size, long int msgtyp, int msgflag);
size实际上是指正文段的大小,总大小应该是size+4字节,接收是同样的意思
msgflag: IPC_NOWAIT
msgsnd()为阻塞函数,当消息队列容量满或者消息个数满会阻塞,如果消息队列被删除,则EIDRM错误,被信号中断E_INTR。
如果设置IPC_NOWAIT会返回-1并且置EAGAIN错误
msgrcv() long int msgtyp if == 0 接收第一个消息
if > 0 接收类型等于msgtyp的第一个消息
if < 0 接收类型等于或者小于msgtyp绝对值的第一个消息
b。 信号量
struct semid_ds {
struct ipc_perm sem_perm; 包含信号量资源的属主和访问权限
struct sem *sem_base; 指向信号量集合的指针
unsigned short int sem_nsems; 集合中信号的个数
time_t sem_otime; 最后一次操作的时间
time_t sem_ctime; 最后一次修改的时间
}
struct sem {
unsigned short semval; 当前信号量值
pid_t sempid; 最后修改信号量的进程
unsignde short semcnt; 等待进行p操作的进程数
unsigned short semzcnt; 等待semval为0的进程数
}
int semget(key_t key, int semnum, int flag)
semnum信号集合中有几个信号量
flag IPC_CREAT IPC_EXCL
semctl(int semid, int semnum, int cmd, union semun arg) 可以为信号量初始值,删除信号量设置权限等
semnum 为信号量集合中的某个信号量操作
cmd SETVAL IPC_RMID
union semun {
short val; 设置信号量的值
struct semid_ds* buf; 设置或者获得semid_ds结构
unsigned short* array; 指向信号量的数组,用于集体初始化
} arg;
信号量操作
int semop(int semid, struct sembuf* buf, int bufsize);
struct sembuf {
short semnum; 信号量集合中的信号量编号
short val; val>0进行v操作加val val<0进行p操作减val val=0时阻塞等待信号量为0
short flag; IPC_NOWAIT IPC_UNDO当执行pv操作之后,进程突然终止没有进行相应的vp操作
}buf;
c。共享存储
shmget(key_t key, int size, int flag)
size为n时表示获得或者创建这么大的共享段
size为0时表示直接获得整个共享段
size大于创建的共享段时,返回错误
(创建时指定n, 获得时一般直接为 0)
struct shmid_ds {
struct ipc_perm shm_perm;
size_t shm_segsz 大小
pid)t shm_pid 最后操作的进程id
pid)t shm_cpid 创建的进程id
shmatt_t shm_nattch 当前连接数
time_t shm_atime 最后调用shmat的时间
time_t shm_dtime 最后调用shmdt的时间
time_t shm_ctime 最后调用shmctl的时间
}
shmctl(int shmid, int cmd, struct shmid_d* buf);
cmd IPC_STAT IPC_SET IPC_RMID SHM_LOCK SHM_UNLOCKroot用户专用
void* shmat(int shmid, const void* shmaddr, int flag);
shmaddr一般为0,内核自动为程序一个连接到共享内存段的地址返回给进程
flag SHM_RDONLY SHM_RND(当shmaddr设置为自己的值时,shm_rnd标志设置后,将会对这个地址做适当的截断以适合系统的对齐)
int shmdt(const void* shmaddr);
阅读(1397) | 评论(0) | 转发(0) |