#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <semaphore.h>//信号量头文件
#include <signal.h>
#define MAX_PIPE_CAPACIPY 100
int main()
{
int fd[2];
sem_t *Mutex;
sem_t *send1, *send2, *send3;
sem_t *receive1, *receive2, *receive3;
//创造有名信号量
/*
创建有名信号量,默认值都为0
sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value);
name 信号量的外部名字
oflag 选择创建或打开一个现有的信号量
O_CREAT | O_RDWR 若不存在则创建,若存在则直接打开
mode 权限位
权限0666:
第一个 0 表示这个数是八进制
第一个 6 表示文件拥有者有读写权,但没有执行权限
第二个 6 表示文件拥有者同组用户有读写权限,但没有执行权限
第三个 6 表示其它用户有读写权限,但没有执行权限
value 信号量初始值 该初始不能超过 SEM_VALUE_MAX,这个常值必须低于为32767
此次实验中默认为0
返回值:成功时返回指向信号量的指针,出错时为SEM_FAILED
*/
Mutex = sem_open("Mutex", O_CREAT, 0666, 1);//管道使用信号量
send1 = sem_open("send1", O_CREAT, 0666, 1);//线程消息信号量,为一,表明子进程有消息发送,或者父进程有消息接受,
send2 = sem_open("send2", O_CREAT, 0666, 1);
send3 = sem_open("send3", O_CREAT, 0666, 1);
receive1 = sem_open("receive1", O_CREAT, 0666, 0);
receive2 = sem_open("receive2", O_CREAT, 0666, 0);
receive3 = sem_open("receive3", O_CREAT, 0666, 0);
int ret = pipe(fd);//创建无名管道,fd{0}只能读,fd{1}只能写,如果进程错误输出错误
if (ret == -1)
{
printf("pipe create error\n");
exit(-1);
}
//定义三个进程,创建三个信号量
pid_t pid1;
pid_t pid2;
pid_t pid3;
pid1 = fork();
if(pid1 > 0)
{
pid2 = fork();
if(pid2 > 0)
{
pid3 = fork();
}
}
//pid不正常,则从系统中删除有名信号量,推出程序
if(pid1 < 0 || pid2 < 0 || pid3 < 0)
{
sem_unlink("Mutex");
sem_unlink("send1");
sem_unlink("send2");
sem_unlink("send3");
sem_unlink("receive1");
sem_unlink("receive2");
sem_unlink("receive3");
exit(0);//正常运行程序并退出程序
}
/*
sem_destroy(sem_t *sem); //销毁一个信号量
int sem_wait(sem_t *sem); //P操作申请信号量
int sem_post(sem_t *sem); //V操作释放信号量
*/
/*
这里通过对pid==0找到子进程,因为子进程的fork()返回值为0,父进程fork返回的是子进程的进程号,即process_id,然后管道的通信过程必然是互斥的,每个进程发送信息要等到管道空闲。
*/
if(pid1 == 0)
{
close(fd[0]);//fd[0]对应管道的读口
sem_wait(send1);//前面我们定义了send1为1,此处说明子进程产生消息。
sem_wait(Mutex);//产生消息后,等待管道的使用权。
char buf[3]="111";
write(fd[1], buf, sizeof(buf));//在子进程中写入,
printf("pid:%d 进程1放入数据:%s\n",getpid(),buf);
sleep(1);
sem_post(Mutex);//释放信号量
sem_post(receive1);
}
else if(pid2 == 0)
{
close(fd[0]);
sem_wait(send2);
sem_wait(Mutex);
char buf[3]="222";
write(fd[1], buf, sizeof(buf));
printf("pid:%d 进程2放入数据:%s\n",getpid(),buf);
sleep(1);
sem_post(Mutex);
sem_post(receive2);
}
else if(pid3 == 0)
{
close(fd[0]);
sem_wait(send3);
sem_wait(Mutex);
char buf[3]="333";
write(fd[1], buf, sizeof(buf));
printf("pid:%d 进程3放入数据:%s\n",getpid(),buf);
sleep(1);
sem_post(Mutex);
sem_post(receive3);
}
else//父进程
{
close(fd[1]);//关闭写,
sem_wait(receive1);//读数据阻塞
sem_wait(receive2);
sem_wait(receive3);
sem_wait(Mutex);
char str[4096];
read(fd[0], str, 4096);//读口读到的数据放在str里面
printf("pid:%d 父进程接收数据:%s\n", getpid(), str);
sleep(1);
sem_post(Mutex);
sem_post(send1);
sem_post(send2);
sem_post(send3);
}
return 0;
}
杭电操作系统实验三-浅析
最新推荐文章于 2023-11-07 20:34:04 发布