7034|2

492

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

Linux信号量实现进程的同步与互斥 [复制链接]

10芯积分
过桥问题
一座小桥(最多只能承重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
#include
#include
/*
*函数类型:北岸去南岸进程函数
*功能:北岸前往南岸人的进程,并创建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("\nCNorth To South-pass North bridge\n");

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

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

                            //V操作信号量south和load
                            sem_v(south);
                            sem_v(load);
                            printf("\nCSouth To North-arrive South\n");
                        }
                       
                        /*通过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("\nDNorth To South-pass North bridge\n");

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

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

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

                        /*通过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("\nENorth To South-pass North bridge\n");

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

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

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

        exit(0);
}


/* SouthtoNorth.c */

#include "move.h"
#include
#include
#include
#include
#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\n");
        }
        /*打开管道*/
        fd = open(MYFIFO, O_RDWR);
        if (fd == -1)
        {
                printf("Open fifo error\n");
                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("\nASouth To North-pass South bridge\n");

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

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

            //V操作信号量north和load
            sem_v(north);
            sem_v(load);
            printf("\nASouth To North-arrive North\n");               
        }
       
        /*通过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("\nBSouth To North-pass South bridge\n");

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

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

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

        /*通过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("\nCSouth To North-pass South bridge\n");

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

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

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

        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
#include

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}



此帖出自Linux开发论坛

最新回复

怎么解决的,我很好奇,为什么没有move.h文件  详情 回复 发表于 2016-12-31 14:04

赞赏

1

查看全部赞赏

点赞(1) 关注

回复
举报

492

帖子

0

TA的资源

一粒金砂(高级)

沙发
 
自己已经解决。。
此帖出自Linux开发论坛
 
 

回复
嘻嘻哈哈你麻痹 该用户已被删除
板凳
 
提示: 作者被禁止或删除 内容自动屏蔽
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表