父进程创建子进程互相通信,父进程从指定文件中每次读取一行放入共享内存中,子进程将共享内存的内容写入另一个文件末尾。由于子进程是无限循环,父进程结束前必须杀死子进程,进程结束时会释放掉等待的信号量,否则再次运行程序时会直接在创建子进程之前阻塞。
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <signal.h>
using namespace std;
#define SHMKEY 18002 /* 共享内存关键字 */
#define SIZE 1024 /* 共享内存长度 */
#define SEMKEY1 19003 /* 信号灯组1关键字 */
#define SEMKEY2 19004 /* 信号灯组2关键字 */
void syserr(string mes){
cout<<mes<<endl;
exit(1);
}
int creatsem(key_t key)
{
int sid;
semun arg;
if((sid=semget(key,1,0666|IPC_CREAT))==-1)
syserr("semget");
arg.val=1;
if(semctl(sid,0,SETVAL,arg)==-1)
syserr("semctl");
return sid;
}
static void semcall(int,int);
void semWait(int sid){
semcall(sid,-1);
}
void semSignal(int sid){
semcall(sid,1);
}
static void semcall(int sid,int op){
struct sembuf sb;
sb.sem_num=0;
sb.sem_op=op;
sb.sem_flg=0;
if(semop(sid,&sb,1)==-1)
syserr("semop");
}
int main(){
char *segaddr;
int segid,sid1,sid2,i;
//创建共享内存段
if((segid=shmget(SHMKEY,SIZE,IPC_CREAT|0666))==-1)
syserr("shmget");
segaddr=(char *)shmat(segid, 0, 0);
sid1=creatsem(SEMKEY1);
sid2=creatsem(SEMKEY2);
semWait(sid2); //将sid2初始化为0
if(!(i=fork())){
while(1){
semWait(sid2);
ofstream out("/Users/mzy/CLionProjects/shareMemory/outfile.txt",ios::app);
out<<segaddr<<endl;
out.close();
semSignal(sid1);
}
}
ifstream in("/Users/mzy/CLionProjects/shareMemory/input.txt");
semWait(sid1);
//如果没有读完文件内容则不会跳出循环
while(in.getline(segaddr,SIZE)){
semSignal(sid2);
semWait(sid1);
}
semSignal(sid1);
//读文件结束,1s后杀死子进程
sleep(1);
kill(i,SIGKILL);
return 0;
}