使用fifo和信号灯实现进程间通信

环境:linux C

功能:使用fifo和信号灯实现进程间通信

/*create_fifo.c*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>


int main()
{
if(mkfifo("myfifo",0666) != 0)
{
perror("mkfifo");
exit(-1);
}
printf("myfifo created successfully\n");
return 0;
}

/*write_fifo.c*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/types.h>//ftok()
#include <sys/ipc.h> //ipc对象头文件
#include <sys/sem.h>//信号灯机制头文件
#include <errno.h>
#define N 32
#define READ 0 //信号灯集合中信号量(读资源)编号
#define WRITE 1 //信号灯集合中信号量(写资源)编号


//信号灯初始化共用体定义
union semun
{
int val;struct semid_ds * buf;
unsigned short * array;
struct seminfo * _buf;
};




//封装一个对信号灯所有信号量进行初始化函数
void init_sem(int semid, int s[],int n)
{
int i;
union semun myun;




for(i=0; i<n; i++)
{
myun.val = s[i];
semctl(semid, i, SETVAL, myun);
}




}




//封装一个信号灯某个信号量进行pv操作函数
void pv_sem(int semid, int num, int op)
{
struct sembuf buf;
buf.sem_num = num;
buf.sem_op = op;
buf.sem_flg = 0;
semop(semid,&buf,1);
}


int main(int argc, char * argv[])
{
//查参
if(argc != 2)
{
printf("usage: %s <path>\n",argv[0]);
exit(-1);
}
int pfd;
char buf[N];
//使用文件IO打开写端
if((pfd = open("myfifo",O_WRONLY)) < 0)
{
perror("open");
exit(-1);
}
printf("write opend\n");

FILE *fp;
if((fp = fopen(argv[1],"r+")) == NULL)
{
perror("fopen");
exit(-1);
}

int s[] = {0,1};
int semid;
key_t key;
//创建key
if((key = ftok(".",'s')) == -1)
{
perror("ftok");
exit(-1);
}
//创建与key关联的信号灯集
if((semid = semget(key,2,IPC_CREAT|0666|IPC_EXCL)) < 0)
{
if(errno == EEXIST)
semid = semget(key,2,0666);
else
{
perror("semget");
exit(-1);
}
}
else
init_sem(semid,s,2);



while(fgets(buf,N,fp) != 0)
{
pv_sem(semid,WRITE,-1);
write(pfd,buf,N);
pv_sem(semid,READ,1);
}


printf("%s的内容已全部写入fifo\n",argv[1]);
//关闭有名管道文件写端,文件流指针,信号灯集
close(pfd);
fclose(fp);
semctl(semid,0,IPC_RMID);
return 0;

}

/*read_fifo.c*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/types.h>//ftok()
#include <sys/ipc.h> //ipc对象头文件
#include <sys/sem.h>//信号灯机制头文件
#include <errno.h>
#define N 32
#define READ 0 //信号灯集合中信号量(读资源)编号
#define WRITE 1 //信号灯集合中信号量(写资源)编号


//信号灯初始化共用体定义
union semun
{
int val;struct semid_ds * buf;
unsigned short * array;
struct seminfo * _buf;
};




//封装一个对信号灯所有信号量进行初始化函数
void init_sem(int semid, int s[],int n)
{
int i;
union semun myun;




for(i=0; i<n; i++)
{
myun.val = s[i];
semctl(semid, i, SETVAL, myun);
}




}




//封装一个信号灯某个信号量进行pv操作函数
void pv_sem(int semid, int num, int op)
{
struct sembuf buf;
buf.sem_num = num;
buf.sem_op = op;
buf.sem_flg = 0;
semop(semid,&buf,1);
}


int main(int argc, char * argv[])
{
//查参
if(argc != 2)
{
printf("usage: %s <path>\n",argv[0]);
exit(-1);
}
int pfd;
char buf[N];
//使用文件IO打开写端
if((pfd = open("myfifo",O_RDONLY)) < 0)
{
perror("open");
exit(-1);
}
printf("READ opend\n");

FILE *fp;
if((fp = fopen(argv[1],"a+")) == NULL)
{
perror("fopen");
exit(-1);
}

int s[] = {0,1};
int semid;
key_t key;
//创建key
if((key = ftok(".",'s')) == -1)
{
perror("ftok");
exit(-1);
}
//创建与key关联的信号灯集
if((semid = semget(key,2,IPC_CREAT|0666|IPC_EXCL)) < 0)
{
if(errno == EEXIST)
semid = semget(key,2,0666);
else
{
perror("semget");
exit(-1);
}
}
else
init_sem(semid,s,2);



while(1)
{


pv_sem(semid,READ,-1);
if(read(pfd,buf,N) == 0)
break;
fputs(buf,fp);
pv_sem(semid,WRITE,1);
}


printf("fifo的内容已全部写入%s\n",argv[1]);
//关闭有名管道文件读端,文件流指针,信号灯集
close(pfd);
fclose(fp);
semctl(semid,0,IPC_RMID);
return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37051576/article/details/79422207