杭电操作系统实验三-浅析

#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;
}


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值