Linux实验 - pv操作-同步

二、实验要求及完成情况

实验要求 :

实验 11c -3 pv 操作-同步

  1.  写进程向缓冲区写入内容,读进程读出。
  2.  用pv操作实现读写进程间的同步。

完成情况 :

    本实验通过用父子进程来模拟读者和写者,并完成他们之间通信的同步操作。具体来讲,首先将读者和写者之间的”桥梁”—临界区用文件来代替,子进程作为写者向文件中写数据,父进程作为读者向文件中读数据,读完数据并清空数据(相当于模拟了取走数据)。

三、设计与实现

   

同步的示意图 :

   

定义两个变量 emptyid 和 fullid ,作为同步信号量。在上面的图中表示 s1 和 s2 。

    

 

在读者中 :

                                         

在写者中:

                                          

思路 :  用fork() 创建子进程,子进程写数据,父进程读数据,临界区是文件。

流程图

                          

 

四、运行结果及分析

运行结果 

           

 

五、源码

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/sem.h>
#include<sys/shm.h>
union semun{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

int emptyid;
int fullid;                                 //同步信号量

int main(int argc , char *argv[])
{
    int chld;
    
    struct sembuf P,V;
    union semun arg;
    char tmp[128] ; 
    int shmid;
    char buffer[256];
    //申请只有一个信号量的信号量集
    FILE *fd1 ,*fd2 ;  
    emptyid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);
    fullid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);
    //分别对每个信号量赋初值
    arg.val=1;
    if(semctl(emptyid,0,SETVAL,arg)==-1)
        perror("semctl setval error");
    arg.val=0;
    if(semctl(fullid,0,SETVAL,arg)==-1)
        perror("semctl setval error");
    //定义PV操作 
    P.sem_num=0;
    P.sem_op=-1;
    P.sem_flg=SEM_UNDO;
    V.sem_num=0;
    V.sem_op=1;
    V.sem_flg=SEM_UNDO;
    while((chld=fork())==-1);
    if(chld>0)
    {// 父进程
        while(1)
        {
            semop(fullid,&P,1);
            fd2 = fopen(argv[1],"r") ;
            fscanf(fd2,"%s",tmp) ;
            printf("父进程  reading-----\n") ;
            printf("ytu.txt 's content is : %s \n",tmp) ;

            // 父进程读完数据要清空
            
            fclose(fd2) ;
            
            fd2 = fopen(argv[1],"w") ; 
            fclose(fd2) ;
            
            semop(emptyid,&V,1); // 告诉子进程可以写了
            if(strncmp(tmp,"end",3)==0)
                break;
        }
        wait(0);
        printf("Parent exit!\n");
        exit(0);
    }
    else
    { // 子进程完成写
        while(1)
        {
            //fd1 = fopen(argv[1] ,"w") ; // 只写
            semop(emptyid,&P,1);
            fd1 = fopen(argv[1],"a") ; 
            // 只写追加 ,保证是父进程先将文件里的数据读出并清空,
            // 而不是子进程覆盖的数据
            puts("Enter your text:");
            printf("子进程  writing ---\n") ;
            scanf("%s",buffer);
            fprintf(fd1,"%s",buffer);// 写入到文件中
           // printf("write : %s \n" ,buffer) ;
            fclose(fd1) ; 
            semop(fullid,&V,1);
            if(strncmp(buffer,"end",3)==0)
            {
                sleep(1);
                break;
            }
        }
        printf("Child exit!\n");
        exit(0);
    }
    return 0 ;
}
发布了385 篇原创文章 · 获赞 105 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_41661809/article/details/104222866
今日推荐