linux进程间通信

早期进程间通信

一、无名管道

1、特点:

  • 只能用于具有亲缘关系的进程间通信
  • 单工通信模式,具有固定的读端和写端
  • 无名管道创建时会返回两个文件描述符,分别用于读写管道

2、相关函数:

#include <unistd.h>
int pipe(int pfd[2]);
  • 成功返回0,失败返回EOF
  • pfd包含两个元素的整形数组,用来保存文件描述符
  • pfd[0]用于读管道,pfd[1]用于写管道

3、读管道

写端存在

  • 有数据,read返回实际读取的字节数
  • 无数据,进程读阻塞

写端不存在

  • 有数据,read返回实际读取的字节数
  • 无数据,read返回0

4、写管道

读端存在

  • 有空间,write返回实际写入的字节数
  • 无空间,进程写阻塞

读端不存在

  • 无论有无空间,程序都会异常结束,管道断裂

二、有名管道

1、特点

  • 对应管道文件,可用于任意进程之间进行通信
  • 打开管道时可指定读写方式
  • 通过文件IO操作,内容存放在内存中
  • 只有读端存在时,有名管道打开会阻塞

无论是有名管道还是无名管道,当读写端全部关闭时,管道存放在内存中的内容都会被自动释放

2、相关函数:

#include <unistd.h>
#include <fcntl.h>
int mkfifo(const char *path,mode_t mode);
  • 成功返回0,失败返回EOF
  • path创建的管道文件路径
  • mode管道文件权限,如0666

三、信号

1、信号的相关概念

  • 信号时在软件层次上对中断机制的一种模拟,是一种异步通信方式
  • linux内核通过信号通知用户进程,不同信号类型代表不同事件
  • linux对早期unix信号机制进行了扩展
  • 进程对信号有不同响应方式:
    1、缺省方式
    2、忽略信号
    3、捕捉信号

2、信号发送

#include <unistd.h>
#include <signal.h>
int kill(pid_t pid, int sig);
int raise(int sig);
  • 成功返回0,失败返回EOF
  • pid接受进程的进程号;0代表同组进程;-1代表所有进程
  • sig信号类型
  • raise函数只能给自己这个进程发信号
int alarm(unsigned int seconds);
  • 成功时返回上个定时器的剩余时间,失败返回EOF
  • seconds定时器的时间
  • 一个进程中只能设定一个定时器,时间到时产生SIGALRM
  • 该函数常用于超时检测
int pause(void);
  • 进程一直阻塞,直到被信号中断
  • 被信号中断后返回-1,errno为EINTR

3、设置信号相应方式

#include <unistd.h>
#include <signal.h>
void (*signal(int signo,void (*handler)(int)))(int);
  • 成功时返回原先的信号处理函数,失败时返回SIG_ERR
  • signo要设置的信号类型
  • handler指定的信号处理函数:SIG_DFL代表缺省方式;SIG_IGN代表忽略信号
void handler (int signo)
{
	if (SIGINT == signo)
	{
		printf("I have got SIGINT\n");
	}
	if (SIGQUIT == signo)
	{
		printf("I have got SIGQUIT\N");
	}
}

int main()
{
	signal(SIGINT,handler);
	signal(SIGQUIT,handler);
	while(1)
	{
		pause();
	}
	return 0;
}

System V IPC

一、概念

  • IPC对象包含:共享内存、消息队列、信号灯集
  • 每个IPC对象有唯一的ID
  • IPC对象创建后一直存在,直到被显式地删除
  • 每个IPC对象有一个关联的KEY
  • ipcs查看IPC对象,ipcrm删除IPC对象

二、相关函数

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *path, int proj_id);
  • 成功时返回合法key值,失败时返回EOF
  • path存在且可访问的文件的路径
  • proj_id用于生成key的数字,不能为0
int main()
{
	key_t key;

	if((key = ftok(".",'a')) == -1)
	{
		peeror("key");
		exit(-1);
	}
}

三、共享内存

1、特点

  • 共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝
  • 共享内存在内核空间创建,可被进程映射到用户空间访问,使用灵活
  • 由于多个进程可同时访问共享内存,因此需要同步和互斥机制配合使用

2、使用步骤

  • 创建/打开共享内存
  • 映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
  • 读写共享内存
  • 撤销共享内存映射
  • 删除共享内存对象

3、相关函数

int shmget(key_t key, int size, int shmflg);
  • 成功时返回共享内存的id,失败时返回EOF
  • key 和共享内存关联的key,IPC_PRIVATE或ftok生成
  • shmflg 共享内存标志位IPC_CREAT|0666
void *shmat(int shmid,const void *shmaddr, int shmflg);
  • 成功时返回映射后的地址,失败时返回(void *)-1
  • shmid 要映射的共享内存id
  • shmaddr 映射后的地址,NULL表示由系统自动映射
  • shmflg 标志位0表示可读写,SHM_RDONLY表示只读
void *shmdt(void *shmaddr);
  • 成功时返回0,失败时返回EOF
  • 不使用共享内存时应撤销映射
  • 进程结束时自动撤销
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • 成功时返回0,失败时返回EOF
  • shmid 要映射的共享内存id
  • cmd 要执行的操作 IPC_STAT,IPC_SET,IPC_RMID
  • buf 保存或设置共享内存属性的地址

4、使用时注意事项

  • 每块共享内存大小有限制 ipcs -l
  • 共享内存删除的时间点
    (1)shmctl添加删除标记
    (2)nattach变成0时真正删除

四、消息队列

1、特点

  • 消息队列由消息队列ID来唯一标识
  • 消息队列就是一个消息的列表,用户可以在消息队列中添加消息、读取消息等
  • 消息队列可以按照类型来发送/接收消息

2、使用步骤

  • 打开/创建消息队列
  • 向消息队列发送消息
  • 从消息队列接收消息
  • 控制消息队列

3、相关函数

int msgget(key_t key,int msgflg);
  • 成功时返回消息队列id,失败返回EOF
  • key 和消息队列关联的key,IPC_PRIVATE或ftok
  • msgflg 标志位 IPC_CREAT|0666
int msgsnd(int msgid, const void *msgp,size_t size, int msgflg);
  • 成功时返回0,失败返回EOF
  • msgid 消息队列id
  • msgp 消息缓冲区地址
  • size 消息正文长度
  • msgflg 标志位0或IPC_NOWAIT
int msgrcv(int msgid, void *msgp, size_t size, long msgtype, int msgflg);
  • 成功时返回0,失败返回-1
  • msgid 消息队列id
  • msgp 消息缓冲区地址
  • size 指定接收的消息长度
  • msgtype 消息类型
  • msgflg 标志位0或IPC_NOWAIT
int msgctl(int msgid, int cmd, struct msqid_ds *buf);
  • 成功时返回0,失败返回-1
  • msgid 消息队列id
  • cmd 要执行的操作 IPC_STAT/IPC_SET/IPC_RMID
  • buf 存放消息队列属性的地址

4、消息格式

  • 通信双方首先定义好统一的消息格式
  • 用户根据应用需求定义结构体类型
  • 首成员类型为long,代表消息类型(正整数)
  • 其他成员都属于消息正文
typedef struct
{
	long mtype;			// 消息类型 应当是一个正整数
	char mtext[64];		// 消息正文
}MSG;
#define LEN (sizeof(MSG) - sizeof(long))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值