Linux信号量实现进程的同步与互斥

2019-03-26 12:25发布

过桥问题一座小桥(最多只能承重2个人)横跨南北两岸,任意时刻同一方向只允许一个人过桥,南侧桥段和北侧桥段较窄只能通过一人,桥中央一处宽敞,允许两个人通过或歇息。因此,过桥问题就是采用某种机制,使得两岸的人可以顺利地过桥,同时又能保证桥的安全性。(1)根据上述对于过桥问题的描述,使用Linux的信号量机制编程解决该问题。通过本课设掌握Linux进程创建的方法,掌握信号量使用方法。(2)设计要求设计的系统要求实现以下功能。l       编写2段程序,程序1创建3个子进程,分别编号A、B、C,用于模拟从南岸前往北岸的人;程序2创建3个子进程,分别编号C、D、E,用于模拟从北岸前往南岸的人。l       通过向屏幕输出语句模拟过桥过程,如输出“南往北-到桥中间”表示从南岸前往北岸的人到达了桥中间;输出“南往北-到达北岸”表示从南岸前往北岸的人到达了北岸。通过观察输出语句,可以发现过桥时是否发成冲突。l       使用Linux的信号量机制,编写解决过桥问题的代码。l       要求给出编译所用到的makefile文件。
     这个题目。。我写的代码。。能够单方面运行成功,合在一起就不可以。。求教各位Linux大神,。。如何解决啊?

/* NorthtoSouth.c */

#include "move.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
/*
*函数类型:北岸去南岸进程函数
*功能:北岸前往南岸人的进程,并创建3个子进程充当3个人
*/
int main(void)
{

        int load, south, north;
        pid_t pid_C, pid_D, pid_E;

        /* 获得信号量 */
        load = semget(ftok(".", 'a'), 1, 0666);   //获得load信号量
        south = semget(ftok(".", 'b'), 1, 0666);  //获得south信号量
        north = semget(ftok(".", 'c'), 1, 0666);  //获得north信号量

        if (load == -1)
        {       
                perror("SouthtoNorth is'nt exist");
        }
        if (south == -1)
        {       
                perror("SouthtoNorth is'nt exist");
                exit(1);
        }
        if (north == -1)
        {       
                perror("SouthtoNorth is'nt exist");
                exit(1);
        }

        /*调用fork函数创建第一个子进程C,其返回值为pid_C*/
        pid_C = fork();
        /*调用fork函数创建第二个子进程D,其返回值为pid_D*/
        pid_D = fork();
        /*调用fork函数创建第三个子进程E,其返回值为pid_E*/
        pid_E = fork();

        /*通过pid_C的值来判断fork函数的返回情况,首先进行出错处理*/
        do
        {
                if(pid_C ==  -1)
                {
                             exit(1);   //异常退出
                        }
                        else if (pid_C == 0) /*返回值为0代表子进程*/
                        {
                            //P操作信号量load和north
                            sem_p(load);
                            sem_p(north);
                            printf(" CNorth To South-pass North bridge ");

                            //V操作信号量north
                            sem_v(north);
                            printf(" CNorth To South-arrive bridge Center ");

                            //P操作信号量south
                            sem_p(south);
                            printf(" CNorth To South-pass South bridge ");

                            //V操作信号量south和load
                            sem_v(south);
                            sem_v(load);
                            printf(" CSouth To North-arrive South ");
                        }
                       
                        /*通过pid_D的值来判断fork函数的返回情况,首先进行出错处理*/
                        if(pid_D ==  -1)
                        {
                             exit(1);    //异常退出
                        }
                        else if (pid_D == 0) /*返回值为0代表子进程*/
                        {
                            //P操作信号量load和north
                            sem_p(load);
                            sem_p(north);
                            printf(" DNorth To South-pass North bridge ");

                            //V操作信号量north
                            sem_v(north);
                            printf(" DNorth To South-arrive bridge Center ");

                            //P操作信号量south
                            sem_p(south);
                            printf(" DNorth To South-pass South bridge ");

                            //V操作信号量south和load
                            sem_v(south);
                            sem_v(load);
                            printf(" DSouth To North-arrive South ");
                        }

                        /*通过pid_E的值来判断fork函数的返回情况,首先进行出错处理*/
                        if(pid_E ==  -1)
                        {
                            exit(1);   //异常退出
                        }
                        else if (pid_E == 0) /*返回值为0代表子进程*/
                        {
                           //P操作信号量load和north
                            sem_p(load);
                            sem_p(north);
                            printf(" ENorth To South-pass North bridge ");

                            //V操作信号量north
                            sem_v(north);
                            printf(" ENorth To South-arrive bridge Center ");

                            //P操作信号量south
                            sem_p(south);
                            printf(" ENorth To South-pass South bridge ");

                            //V操作信号量south和load
                            sem_v(south);
                            sem_v(load);
                            printf(" ESouth To North-arrive South ");
                        }

        exit(0);
}


/* SouthtoNorth.c */

#include "move.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define MYFIFO                        "myfifo"

void *SouthtoNorth(void *arg);
void *NorthtoSouth(void *arg);
int fd;   //有名管道标识符

/*
*函数类型:主函数main
*功能:创建信号量 初始化信号量 调用两个子进程的函数
*/
int main()
{
        int load, south, north;
        pid_t pid_A, pid_B, pid_C;

        load = semget(ftok(".", 'a'), 1, 0666|IPC_CREAT);   //创建一个信号量
        south = semget(ftok(".", 'b'), 1, 0666|IPC_CREAT);  //创建一个信号量
        north = semget(ftok(".", 'c'), 1, 0666|IPC_CREAT);  //创建一个信号量

        init_sem(load,2);    //初始化共享信号量load为2
        init_sem(south,1);   //初始化南岸互斥信号量为1
        init_sem(north,1);   //初始化北岸互斥信号量为1       

        /*创建有名管道*/
        if((mkfifo(MYFIFO, O_CREAT|O_EXCL) < 0) && (errno != EEXIST))
        {
                printf("Cannot create fifo ");
        }
        /*打开管道*/
        fd = open(MYFIFO, O_RDWR);
        if (fd == -1)
        {
                printf("Open fifo error ");
                return fd;
        }
       

        /*调用fork函数创建第一个子进程A,其返回值为pid_A*/
        pid_A = fork();
        /*调用fork函数创建第二个子进程B,其返回值为pid_B*/
        pid_B = fork();
        /*调用fork函数创建第三个子进程C,其返回值为pid_C*/
        pid_C = fork();

        /*通过pid_A的值来判断fork函数的返回情况,首先进行出错处理*/
        if(pid_A ==  -1)

        {
            exit(1); //异常退出
        }
        else if (pid_A == 0) /*返回值为0代表子进程*/
        {
            //P操作信号量load和south
            sem_p(load);
            sem_p(south);
            printf(" ASouth To North-pass South bridge ");

            //V操作信号量south
            sem_v(south);
            printf(" ASouth To North-arrive bridge Center ");

            //P操作信号量north
            sem_p(north);
            printf(" ASouth To North-pass North bridge ");

            //V操作信号量north和load
            sem_v(north);
            sem_v(load);
            printf(" ASouth To North-arrive North ");               
        }
       
        /*通过pid_B的值来判断fork函数的返回情况,首先进行出错处理*/
        if(pid_B ==  -1)
        {
           exit(1);
        }
        else if (pid_B == 0) /*返回值为0代表子进程*/
        {
             //P操作信号量load和south
            sem_p(load);
            sem_p(south);
            printf(" BSouth To North-pass South bridge ");

            //V操作信号量south
            sem_v(south);
            printf(" BSouth To North-arrive bridge Center ");

            //P操作信号量north
            sem_p(north);
            printf(" BSouth To North-pass North bridge ");

            //V操作信号量north和load
            sem_v(north);
            sem_v(load);
            printf(" BSouth To North-arrive North ");       
        }

        /*通过pid_C的值来判断fork函数的返回情况,首先进行出错处理*/
        if(pid_C ==  -1)
        {
             exit(1);
        }
        else if (pid_C == 0) /*返回值为0代表子进程*/
        {
                //P操作信号量load和south
            sem_p(load);
            sem_p(south);
            printf(" CSouth To North-pass South bridge ");

            //V操作信号量south
            sem_v(south);
            printf(" CSouth To North-arrive bridge Center ");

            //P操作信号量north
            sem_p(north);
            printf(" CSouth To North-pass North bridge ");

            //V操作信号量north和load
            sem_v(north);
            sem_v(load);
            printf(" CSouth To North-arrive North ");       
        }

        exit(0);
}



/* move.c */

#include "move.h"

int init_sem(int sem_id, int init_value)
{
        union semun sem_union;
        sem_union.val = init_value;
        if (semctl(sem_id, 0, SETVAL, sem_union) == -1)
        {
                perror("Initialize semaphore");               
                return -1;
        }
        return 0;
}

int del_sem(int sem_id)
{
        union semun sem_union;
        if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
        {
                perror("Delete semaphore");
                return -1;
        }
}

int sem_p(int sem_id)
{
        struct sembuf sem_b;
        sem_b.sem_num = 0; /*id*/
        sem_b.sem_op = -1; /* P operation*/
        sem_b.sem_flg = SEM_UNDO;
       
        if (semop(sem_id, &sem_b, 1) == -1) /*1:first struct*/
        {
                perror("P operation");
                return -1;
        }
        return 0;
}

int sem_v(int sem_id)
{
        struct sembuf sem_b;
       
        sem_b.sem_num = 0; /* id */
        sem_b.sem_op = 1; /* V operation */       
        sem_b.sem_flg = SEM_UNDO; /* It's tracks be follow, to automatical free for it*/

        if (semop(sem_id, &sem_b, 1) == -1)
        {
                perror("V operation");
                return -1;
        }
        return 0;
}



/* sem_com.h */

#ifndef                SEM_COM_H
#define                SEM_COM_H

#include <sys/ipc.h>
#include <sys/sem.h>

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

int init_sem(int, int);
int del_sem(int);
int sem_p(int);
int sem_v(int);

#endif /* SEM_COM_H */


Makefile文件。。。。

EXEC1 = SouthtoNorth
EXEC2 = NorthtoSouth
OBJS1 = SouthtoNorth.o move.o
OBJS2 = NorthtoSouth.o move.o
HEADERS = move.h

CC = gcc
CFLAGS = -O2

all:${EXEC1} ${EXEC2}
${EXEC1} : ${OBJS1}
        ${CC} ${CFLAGS} ${LDFLAGS} -o $@ $^
${EXEC2} : ${OBJS2}
        ${CC} ${CFLAGS} ${LDFLAGS} -o $@ $^

${OBJS1} : ${HEADERS}
${OBJS2} : ${HEADERS}

.PHONY : clean
clean :
        -rm -f ${OBJS1} ${EXEC1}
        -rm -f ${OBJS2} ${EXEC2}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。