esolodo 发表于 2013-06-06 11:07

linux了解信号量机制,了解并掌握进程同步和互斥机制

本帖最后由 esolodo 于 2013-06-06 11:07 编辑

目的:了解信号量机制,了解并掌握进程同步和互斥机制,熟悉信号量的操作函数,利用信号量实现对共享资源的控制。 
设计要求:编程模拟实现这一问题的程序控制,分析处理过程, 
问题描述:桌子上有一只盘子,最多可容纳两个水果,每次只能放入或取出一个水果。爸爸专向盘子放苹果(apple),妈妈专向盘子中放桔子(orange);两个儿子专等吃盘子中的桔子,两个女儿专等吃盘子中的苹果。请用P、V操作来实现爸爸、妈妈、儿子、女儿之间的同步与互

#include<stdio.h>
#include<unistd.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>


struct dish
{//盘子
        int total_num;//苹果和句子的总个数
        int apple;//苹果的个数
        int orang;//橘子的个数
};
typedef struct dish dish;

union semun
{
        int val;
        struct semid_ds *buf;
        unsigned short *array;
};

int init_sem(int sem_id,int init_val)
{// 将信号量sem_id设置为init_value
        union semun sem_union;
        sem_union.val=init_val;
        if(semctl(sem_id,0,SETVAL,sem_union) == -1)
        {
                printf("semctl init error\n");
                exit(1);
        }
        return 0;
}
int del_sem(int sem_id)
{// 删除sem_id信号量
        union semun sem_union;
        if((semctl(sem_id,0,IPC_RMID,sem_union)) == -1)
        {
                perror("sem delete");
                exit(1);
        }
        return 0;
}
int sem_p(int sem_id)
{// 对sem_id执行p操作
        struct sembuf sem_buf;
        sem_buf.sem_num = 0;//信号量编号
        sem_buf.sem_op = -1;//P操作
        sem_buf.sem_flg = SEM_UNDO;//系统退出前未释放信号量,系统自动释放
        if(semop(sem_id,&sem_buf,1) == -1)
        {
                perror("sem p operation");
                exit(1);
        }
        return 0;
}
int sem_v(int sem_id)
{// 对sem_id执行V操作
        struct sembuf sem_buf;
        sem_buf.sem_num = 0;
        sem_buf.sem_op = 1;//V操作
        sem_buf.sem_flg = SEM_UNDO;
        if(semop(sem_id,&sem_buf,1) == -1)
        {
                perror("sem v operation");
                exit(1);
        }
        return 0;
}

int main()
{
        pid_t temp;
        pid_t mother;
        pid_t father;
        pid_t son;
        pid_t daughter;

        dish *dishs;
        int shmid;//共享区域
        int sem_id;//信号量
        key_t sem_key;

        sem_key = ftok(".",'a');
       //    以0666且create mode创建一个信号量,返回给sem_id
        sem_id = semget(sem_key,1,0666|IPC_CREAT);
        init_sem(sem_id,1);//    将sem_id设为1

        if((shmid = shmget(IPC_PRIVATE,sizeof(dish),IPC_CREAT|0666)) < 0)
        {//获得共享区域号
                printf("shmget error!\n");
                exit(1);
        }
        if((dishs = (dish*)shmat(shmid,0,0)) == (int*) -1)
        {//设置共享区域
                printf("shmat error\n");
                exit(1);
        }

        //初始化盘子
        dishs->total_num = 0;
        dishs->apple = 0;
        dishs->orang = 0;
       
        //创建 妈妈、爸爸、儿子、女儿进程
        if((mother = fork()) < 0)
                        printf("fork()mother prosess error\n");
        if((father = fork()) < 0)
                printf("fork() father prosess error\n");
        if((son = fork())< 0)
                printf("fork() son prosess error\n");
        if((daughter = fork()) < 0)
                printf("fork() daughter prosess error\n");
        temp = getpid();
        if(temp == 0)
        {
                printf("this is mian----------------------------\n");
                printf("The nunber of apples = %d\n",dishs->apple);
                printf("The number of orang = %d \n",dishs->orang);
        }else if(temp = mother)
        {//妈妈放橘子

                if(!sem_p(sem_id))
                {//申请进入盘子放橘子,申请不成功则休眠
                printf("this is mother-----------------------------\n");
                printf("The nunber of apples = %d\n",dishs->apple);
                printf("The number of orang = %d \n",dishs->orang);
                        if(dishs->total_num < 2)
                        {//如果盘子满了,则装不下,就放弃等盘子有容量
                                dishs->orang++;
                                dishs->total_num++;
                                printf("Mama put a orange to the dish\n");
                        }else
                                printf("This dish is full!\n");
                }
                sem_v(sem_id);//释放信号量
                sleep(1);
        }else if(temp == father)
        {//爸爸放苹果
                if(!sem_p(sem_id))
                {//申请进入盘子放苹果,申请不成功则休眠
                printf("this is father-----------------------------\n");
                printf("The nunber of apples = %d\n",dishs->apple);
                printf("The number of orang = %d \n",dishs->orang);

                        if(dishs->total_num < 2)
                        {//如果盘子满了,则装不下,就放弃等盘子有容量
                                dishs->apple++;
                                dishs->total_num++;
                                printf("Baba put a apple to the dish\n");
                        }else
                                printf("The dish is full!\n");
                }
                sem_v(sem_id);//释放信号量
                sleep(1);
        }else if(temp == son)
        {//儿子吃橘子
                if(!(sem_p(sem_id)))
                {//申请进入盘子吃橘子,申请不成功则休眠
                printf("this is son ------------------------------\n");
                printf("The nunber of apples = %d\n",dishs->apple);
                printf("The number of orang = %d \n",dishs->orang);
                        if(dishs->total_num > 0 && dishs->orang > 0)
                        {//如果盘子里没有苹果则等待爸爸放苹果
                                dishs->total_num--;
                                dishs->orang--;
                                printf("The son eat a orange!\n");
                        }else
                                printf("The son have no orange to eat\n");
                        sem_v(sem_id);//释放信号量
                        sleep(1);
                }
        }else if(temp == daughter)
        {//女儿吃苹果
                if(!sem_p(sem_id))
                {//申请进入盘子吃苹果,申请不成功则休眠
                printf("This is daughter---------------------------------\n");
                printf("The nunber of apples = %d\n",dishs->apple);
                printf("The number of orang = %d \n",dishs->orang);
                        if(dishs->total_num > 0 && dishs->apple > 0)
                        {//如果盘子里没有橘子,则女儿等待妈妈放橘子
                                dishs->total_num--;
                                dishs->apple--;
                                printf("The duaghter eat a apple!\n");
                        }else
                                printf("The duaghter have no apple to eat\n");
                        sem_v(sem_id);//释放信号量
                        sleep(1);
                }
        }

        return 0;
}






























斥关系。
页: [1]
查看完整版本: linux了解信号量机制,了解并掌握进程同步和互斥机制