进程通信
以读、拷贝、写三个进程写作完成文件拷贝为例,操作流程大致为:
主进程内申请共享信号量和共享内存区域,并对其做必要的初始化操作。然后再主进程中启动读、拷贝、写三个子进程。用共享信号量控制子进程的操作,用共享内存实现子进程通信。主进程持续等待,直至所有子进程执行完毕,然后释放信号量和共享内存。
申请信号量
传入一个key(2333),申请4个信号量
int semid = semget(2333, 4, IPC_CREAT|0666);
if(semid == -1)
{
return -1;
}
申请共享内存
大小为4+BUF_SIZE+1,前4个字节用于存放每次读取的字节数(整数)
//fork(".", 0)用于产生一个与当前目录有关的key
const int BUF_SIZE = 1024;
int segidS = shmget(ftok(".", 0), BUF_SIZE+5, IPC_CREAT|0666);
if(segidS == -1)
{
return -1;
}
int segidT = shmget(ftok(".", 1), BUF_SIZE+5, IPC_CREAT|0666);
if(segidT == -1)
{
return -1;
}
启动子进程
get:负责从文件读至缓冲区S
copy:负责从缓冲区S复制至缓冲区T
put:负责从缓冲区T写至文件
pid_t p1, p2, p3;
if((p1 = fork()) == 0)
{
execv("./get", NULL);
}
if((p2 = fork()) == 0)
{
execv("./copy", NULL);
}
if((p3 = fork()) == 0)
{
execv("./put", NULL);
}
等待子进程执行
如果文件打开出现异常,则终止程序,否则copy进程会一直陷入等待,导致整个程序僵死
int status;
wait(&status);
if(WEXITSTATUS(status)>1 && WEXITSTATUS(status)<5)
{
exit(-1);
}
wait(&status);
if(WEXITSTATUS(status)>1 && WEXITSTATUS(status)<5)
{
exit(-1);
}
wait(&status);
if(WEXITSTATUS(status)>1 && WEXITSTATUS(status)<5)
{
exit(-1);
}
释放信号量及共享内存
将申请的信号亮和共享内存释放掉
semctl(semid, 0, IPC_RMID, NULL);
shmctl(segidS, IPC_RMID, NULL);
shmctl(segidT, IPC_RMID, NULL);
附:全部源码
PV操作头文件:pv.h
定义了semun结构:这个结构类型semtrl()对信号量赋初值时需要自己定义。
实现了简单的P、V操作。
#ifndef PV_H_INCLUDED
#define PV_H_INCLUDED
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/ipc.h>
union semun {
int val;