进程间通信

进程间通信

进程间通信(IPC)
linux中实现进程间通信的几种方式:

管道

管道的特性:一边写,一边读。这边没有东西,另一端则处于阻塞状态。只有当另一端写入时,一端才能读出数据。
管道又分为几种模式:
单工:例如看电视,一端只能播放,一端只能接收,
半双工:例如对讲机,只能一端放,一端收,一个人说话,另一个人只能听。可以互相都说话。
全双工:例如打电话,两边都可以*说或者听。
linux中一切皆文件:
管道文件的创建方式为:
int pipe(int fds[2])
fds是一个int型的数组。通过调用pipe函数,使得fds的两个值分别为文件描述符的值,这些文件描述符直接映射到对应的管道文件。fds[0]为管道输入端,fds[1]为管道的输出端。
我们可以通过fork子进程的方式来操作管道。
fork时,子进程继承父进程的所有数据,同时也复制出了管道文件描述符,因此我们可以在子进程中输入,输入的话我们将子进程中对应的读文件描述符关闭fds[0]。相对应的,我们将父进程的写文件描述符也关闭fds[1]。
进程间通信
创建管道文件函数:
int mkfifo(const char *name,mode_t mode);
打开管道文件
int fd = open(name, O_RDONLY); 管道一边写一边读;
int fd = open(name, O_WONLY); 只写

消息队列

创建消息队列:
msgget(key_t key, int flags);
key相当于文件名,
创建消息队列: IPC_CREAT | 0644
对应权限 直接或上去, 如果只是想打开 直接填0,否则填错权限 会导致打开错误;
返回值是消息队列的ID。相当于文件描述符

消息队列按照不同的消息类型收发数据

往消息队列中发送数据
msgsnd
msgsnd(int id, ID编号 mssget的返回值
const void *msgbuf, 要发送的信息在哪(结构体)
size_t len, 消息的字节数 不包括结构体中消息类型(channel)的大小,
int flag); 发送的flag 一般写0
返回值:成功返回0,失败返回-1
struct msgbuf{ 消息队列中 的数据类型
long channel; //消息类型(通道号),必须>=1
//随便写,传自己的消息内容
char mtext[1000];
}
进程间通信
msgrcv 从消息队列中取数据, 取出来就拿走了,数据就不存在了
msgrcv(int id,
void *msgp, //取出来的小时放在这里
size_t len, //装消息的大小,不包含消息类型(通道号)。
long mytype, //取那个类型的消息(通道号)
int flag, //一般写0
);

失败返回-1,成功返回成功读取的字节数
当要取的消息类型(通道号)不存在时,会阻塞住,等到另一端往该消息类型(通道号)中写入数据时,这一端才能取到数据, 取消息按照队列方式,先进先出方式。

XXXctl()关闭 干掉其中一个队列

共享内存

进程间通信
共享内存

通过函数打开的共享内存映射区,可用直接通过代码内改变映射物理内存对应的值。

创建或打开共享内存
#inlude

信号量

信号量集:

创建或者打开信号量:
int semget(key_t key,
int nsems, //信号量集中信号量的个数
int flag, //打开0,创建IPC_CREAT | 0644
)
ipcs -s 查看信号量 最后一个信息是 信号量个数,一般为1

设置信号量初值:
semctl(int semid,
int semnum //信号量中的第几个信号量
int cmd, //SETVAL
su, //信号量初值, 是个结构体
)
最后一个参数是联合体
union semun{
int val;
}

查看信号量的值
semctl(semid,
int semnum, //信号量中的第几个信号量
int cmd, //GETVAL
0,
)
返回值,当前信号量的值。

PV操作:PV操作函数
semop( int semid.
struct sembuf sb[], //结构体
int len, //
)
semop(id, sb,1)
id, 数组名, 数组有几个元素
结构体如下:
struct sembuf{
short sem_sum; //信号量的下标
short sem_op; //V操作值为1、P操作值为-1
short sem_flag; // 0
}