linux下进程间通信
信号
信号是进程间相互传递消息的一种方法,只是用来通知某进程发生了什么事件,并不给进程传递任何数据。
#include <sys/types.h> #include <unistd.h> #include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);//系统调用signal用来设定某个信号的处理方法 int kill(pid_t pid, int sig);//系统调用kill来向进程发送一个信号 int pause(void);//系统调用pause等待一个信号 还有alarm/setitmer等
管道
管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入。管道是一个固定大小的缓冲区,写满时会默认被阻塞,读空时程序也会被阻塞。管道包括无名管道和有名管道两种。
- 半双工,数据单向流动
- 单独构成一种独立的文件系统,只存在于内存中
- 数据的读出和写入都是单向的,一进程从管道缓冲区头部读,一进程写入管道缓冲区末尾
#include <unistd.h> //参数数组包含pipe使用的两个文件描述符,fd[0]读管道,fd[1]写管道,用一般的write/read/close函数来读写关闭管道 int pipe(int fd[2]);命名管道FIFO:
FIFO是一个特殊的设备文件,FIFO的路径名存在于文件系统中;不同进程间可以共享数据;使用完后FIFO将继续保存。用mkfifo创建FIFO文件后,一般的文件I/O函数(close、read、write、unlink等)都可用于FIFO。
#include <sys/types.h> #include <sys/stat.h> int mkfifo(const char* pathname, mode_t mode);
消息队列
消息队列是一个消息链表,存放在内核中并由消息队列标识符标识。
#include <sys msg="" h=""> int msgget(key_t key, int msgflg);//创建新消息队列或取得已存在消息队列 size_t msgrcv(int msqid, void* msgp, size_t msgsz, long msgtype, int msgflg);//从队列中取常用信息 int msgsnd(int msgid, const void* msgp, size_t msgsz, int msgflg)//将数据放到消息队列中</sys>
共享内存
两个或更多进程访问同一块内存,共享内存在各种进程间通信方式中效率最高。使用共享内存时,要注意多进程间的同步访问,读写互斥等。
- 分配共享内存
- 需要访问这块共享内存的每个进程将这个共享内存绑定到自己的地址空间
- 绑定共享内存的进程脱离共享内存
- 释放共享内存
#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg)//得到一个共享内存标识符或创建一个共享内存并返回标识符 void *shmat(int shmid, const void *shmaddr, int shmflg)//连接共享内存shmid,把共享内存映射到调用进程的地址空间,随后像本地空间一样访问,返回指向共享存储的指针 int shmdt(const void *shmaddr)//用来断开与共享内存的连接,禁止本进程访问此块内存,shmaddr是shmat返回的值 int shmctl(int shmid, int cmd, struct shmid_ds *buf)//完成对共享内存的控制,cmd为IPC_RMID为删除共享内存
信号量
信号量是一个计数器,代表资源可用数目,用于多进程对共享资源的同步访问。为了获得资源,进程需要执行的操作:1)尝试获得信号量。2)若此信号量的值为正,则进程可以使用资源,并将信号量减1;当进程不再使用资源时,信号量值加1。3)若此信号量值为0,进程进入休眠状态,直至信号量值大于0。Linux提供两种信号量:
- 内核信号量,由内核控制路径使用。
- 用户态信号量,包括POSIX信号量和SYSTEM V信号量。POSIX信号量分为有名信号量和无名信号量,有名信号量值存在文件中,无名信号量值保存在内存中。
#include <sys/sem.h> //创建一个新的信号量或获得一个已存在的信号量。key表示创建或打开信号量集的键,num_sems表示创建的信号量集中的信号量个数, //flag:指出函数的操作类型和读写权限IPC_CREAT如果信号量集不存在,则创建信号量集;IPC_EXCL/IPC_CREAT:如果信号量集已经存在,则调用失败;读写权限ugo(用户、组、其他) int semget(key_t key, int num_sems, int sem_flags); int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);//改变信号量的值 int semctl(int sem_id, int sem_num, int command, ...);总结:消息队列、信号量和共享内存这三种IPC,其结构都用一个非负整数的标识符加以引用,每个IPC对象都与一个键相关联(key_t长整型),键由内核转换成标识符。IPC结构在进程间的传递方式:1) 服务器进程指定键IPC_PRIVATE创建一个新IPC结构,将返回的标识符存放在某处以便客户进程取用;2)在一个公用头文件中定义一个客户进程和服务器进程都认可的键;3)客户进程和服务器进程认同一个路径名和项目ID,调用函数ftok将两个值变换为一个键。
三个get函数(msgget,semget,shmget)如果满足下列两个条件之一,则创建新IPC结构:1)key是IPC_PRIVATE,2)key当前未与特定类型的IPC结构相结合,并且flag中指定了IPC_CREAT位。
套接口
常用的网络通信方式,不再细说。