Linux进程间通信学习笔记

进程间通信

进程间通信(IPC)是指在不同进程之间传播或交换信息

IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信息量、共享存储、Socket、Streams等。其中Socket、Streams支持不同主机上的两个进程IPC

无名管道

通常指无名管道,是UNIX系统IPC最古老的形式

特点
  1. 半双工(只能同时进行一组读写),具有固定的读端和写端
  2. 只能用于具有亲缘关系的进程之间的通信(父子进程/兄弟进程)
  3. 可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write等函数。但它不是普通的文件,不属于其他任何文件系统,只存在内存中。
  4. 管道数据被读取,就没了
原型
#include <unistd.h>
int pipe(int fd[2]);		
//返回值:若成功返回0,失败返回-1

当一个管道建立时,其会创建两个文件描述符:

fd[0]为读而打开,fd[1]为写而打开 用close/write/read 操作

​ 读管道 会等到 管道内有数据再读

命名管道 FIFO

命名管道,是一种文件类型

特点
  1. FIFO可以在无关的进程之间交换数据,与无名管道不同
  2. FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统
原型

mode与open的mode相同。一旦创建FIFO,就可以用一般的文件I/O函数操作它

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);

当open一个FIFO时,是否设置非阻塞标志(O_NONBLOCK)的区别

  • 若没指定O_NOBLOCK(默认),只读open要阻塞到某个其他进程为写而打开此FIFO。只写同理
  • 若制定了O_NONBLOCK,则只读open立即返回。而只写open将出错返回-1。如果没有进程已经为读而打开该FIFO,其errno置ENXIO。

消息队列

消息列表,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。

特点
  1. 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级
  2. 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除
  3. 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取
原型
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
//创建或打开消息队列:成功返回队列ID,失败返回-1
//flg 中还要包括权限


int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//添加消息:成功返回0,失败返回-1

size_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
//读取消息:成功返回消息数据长度,失败返回-1

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
//控制消息队列:成功返回0,失败返回-1
//msgctl可以清除消息队列  IPC_RMID

在以下两种情况下,msgget将创建一个新的消息列表:

  • 如果没有与键值key相对应的消息队列,且flag中包含了IPC_CREAT标志位
  • key参数为IPC_PRIVATE
ftok

系统IPC键值的格式转换函数

系统建立IPC通讯(消息队列、信号量和共享内存)时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。

#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);

共享内存

  1. 创建/打开共享内存
  2. 映射
  3. 数据操作
  4. 释放共享内存
原型
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);
//创建或获取一个共享内存:成功返回共享内存ID,失败返回-1

void *shmat(int shmid, const void *shmaddr, int shmflg);
//连接共享内存到当前进程的地址空间:成功返回指向共享内存的指针,失败返回-1

int shmdt(const void *shmaddr);
//断开与共享内存的连接:成功返回0,失败返回-1

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
//控制共享内存的相关信息:成功返回0,失败返回-1
//IPC_RMID

共享内存大小必须以兆(1024)对齐

信号

对于Linux来说,实际信号是软中断

信号的处理方式有三种忽略捕捉默认动作

  • 忽略信号,大多数信号能使用这种方式处理,但有两种不能被忽略(SIGKILL和SIGSTOP)
  • 捕捉信号,写一个信号处理函数,告诉内核
  • 默认动作,man 7 signal

ps -aux|grep XXX 查看进程

kill -9 数字 杀死进程

信号处理函数的注册

入门函数:signal

发:kill() 操作函数:signal()

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_thandler);
//SIG_IGN 忽略

高级函数:sigaction

收信号:1.用什么绑定函数 2.如何读出消息

#include <signal.h>

int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
//oldact  做备份

struct sigaction {
void     (*sa_handler)(int);
//配置信号处理程序,不接受任何数据,SIG_IGN为忽略   
void     (*sa_sigaction)(int, siginfo_t *, void *);
//配置信号处理程序,能够接收额外数据
//配置1.num  2.结构体 3.指针(NULL无数据 非NULL有数据)
//2.结构体 pid谁发 int数据
sigset_t   sa_mask;
//阻塞关键字的信号集,可以再调用捕捉函数之前,把信号添加到信号阻塞
int        sa_flags;
//影响信号的行为	   SA_SIGINFO标识能够接收数据
};

发信号:1.用什么发 2.怎么放入消息

sigqueue

#include <signal.h>

int sigqueue(pid_t pid, int sig, const union sigval value);

union sigval {
int   sival_int;
void *sival_ptr;
};

信号处理发送函数

信号量

是一个计数器,用于实现进程间的互斥与同步,而不是用于存储进程间通信数据

特点
  1. 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存
  2. 信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作
  3. 每次对信号量的PV操作不仅限于对信号量值加1或减1,可以加减任意正整数
  4. 支持信号量组
临界资源

多道程序系统中存在许多进程,它们共享各种资源,然而有很多资源一次只能供一个进程使用。一次仅允许一个进程使用的资源称为临界资源。

信号量集
P操作:拿锁 semop
V操作:放锁 semop
原型

Linux下的信号量函数都是在通用的信号量数组上进行操作,而不是在一个单一的二值信号量上进行操作

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semget(key_t key, int nsems, int semflg);
//创建或或获取一个信号量组:成功返回信号量集ID,失败返回-1

int semop(int semid, struct sembuf *sops, unsigned nsops);
//对信号量组进行操作,改变信号量的值:成功返回0,失败返回-1

int semctl(int semid, int semnum, int cmd, ...);
//控制信号量的相关信息 cmd初始化SETVAL
					//cmd销毁IPC_RMID

struct sembuf
{
unsigned short sem_num;  /* 信号量集中的第几个信号量 */
short          sem_op;   /* +- 锁*/
short          sem_flg;	/*SEM_UNDO维护进程对信号量的调整值*/
}

union semun {
int              val;    /* Value for SETVAL */
struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
unsigned short  *array;  /* Array for GETALL, SETALL */
struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */
};//semctl第四个参数 设置val(锁的数量)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值