论坛徽章: 2
10 可用积分
本帖最后由 陌路巨额投入 于 2014-11-06 21:16 编辑
过桥问题
一座小桥(最多只能承重2个人)横跨南北两岸,任意时刻同一方向只允许一个人过桥,南侧桥段和北侧桥段较窄只能通过一人,桥中央一处宽敞,允许两个人通过或歇息。因此,过桥问题就是采用某种机制,使得两岸的人可以顺利地过桥,同时又能保证桥的安全性。
根据上述对于过桥问题的描述,使用Linux的信号量机制编程解决该问题。通过本课设掌握Linux进程创建的方法,掌握信号量使用方法。
要求实现以下功能。
编写2段程序,程序1创建3个子进程,分别编号A、B、C,用于模拟从南岸前往北岸的人;程序2创建3个子进程,分别编号C、D、E,用于模拟从北岸前往南岸的人。
通过向屏幕输出语句模拟过桥过程,如输出“南往北-到桥中间”表示从南岸前往北岸的人到达了桥中间;输出“南往北-到达北岸”表示从南岸前往北岸的人到达了北岸。通过观察输出语句,可以发现过桥时是否发成冲突。
使用Linux的信号量机制,编写解决过桥问题的代码。
要求给出编译所用到的makefile文件。
我的错误是:在使用Makefile编译的时候提示:多次定义main 多次定义sem_p以及多次定义sem_v...求各位大神指导下...
我写的代码:
/* sem_com.h */
#ifndef SEM_COM_H
#define SEM_COM_H
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <semaphore.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);
/*定义三个信号量 load用来控制桥上人数,初值为2,表示桥上最多有2人;
north用来控制北段桥的使用,初值为1,用于对北段桥互斥;
south用来控制南段桥的使用,初值为1,用于对南段桥互斥。*/
int load = 2, north = 1, south = 1;
#endif /* SEM_COM_H */
/* sem_com.c */
#include "sem_com.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)
{
perror(" 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;
if (semop(sem_id, &sem_b, 1) == -1)
{
perror("V operation" ;
return -1;
}
return 0;
}
/* NorthtoSouth.c */
#include "sem_com.h"
int main(void)
{
pid_t pid_A, pid_B, pid_C;
/*调用fork函数创建第一个子进程A,其返回值为pid_A*/
pid_A = fork();
/*通过pid_A的值来判断fork函数的返回情况,首先进行出错处理*/
if(pid_A == -1)
{
perror("Fork\n" ;
}
else if (pid_A == 0) /*返回值为0代表子进程*/
{
//P操作信号量load和south
sem_p(load);
sem_p(south);
printf("\nA从南往北-过南桥段\n" ;
//V操作信号量south
sem_v(south);
printf("\nA从南往北-到桥中间\n" ;
//P操作信号量north
sem_p(north);
printf("\nA从南往北-过北桥段\n" ;
//V操作信号量north和load
sem_v(north);
sem_v(load);
printf("\nA从南往北-到达北岸\n" ;
}
/*调用fork函数创建第二个子进程B,其返回值为pid_B*/
pid_B = fork();
/*通过pid_B的值来判断fork函数的返回情况,首先进行出错处理*/
if(pid_B == -1)
{
perror("Fork\n" ;
}
else if (pid_B == 0) /*返回值为0代表子进程*/
{
//P操作信号量load和south
sem_p(load);
sem_p(south);
printf("\nB从南往北-过南桥段\n");
//V操作信号量south
sem_v(south);
printf("\nB从南往北-到桥中间\n");
//P操作信号量north
sem_p(north);
printf("\nB从南往北-过北桥段\n");
//V操作信号量north和load
sem_v(north);
sem_v(load);
printf("\nB从南往北-到达北岸\n");
}
/*调用fork函数创建第三个子进程C,其返回值为pid_C*/
pid_C = fork();
/*通过pid_C的值来判断fork函数的返回情况,首先进行出错处理*/
if(pid_C == -1)
{
perror("Fork\n");
}
else if (pid_C == 0) /*返回值为0代表子进程*/
{
//P操作信号量load和south
sem_p(load);
sem_p(south);
printf("\nC从南往北-过南桥段\n");
//V操作信号量south
sem_v(south);
printf("\nC从南往北-到桥中间\n");
//P操作信号量north
sem_p(north);
printf("\nC从南往北-过北桥段\n");
//V操作信号量north和load
sem_v(north);
sem_v(load);
printf("\nC从南往北-到达北岸\n");
}
exit(0);
}
/* NorthtoSouth.c */
#include "sem_com.h"
int main(void)
{
pid_t pid_C, pid_D, pid_E;
/*调用fork函数创建第一个子进程C,其返回值为pid_C*/
pid_C = fork();
/*通过pid_C的值来判断fork函数的返回情况,首先进行出错处理*/
if(pid_C == -1)
{
perror("Fork\n");
}
else if (pid_C == 0) /*返回值为0代表子进程*/
{
//P操作信号量load和north
sem_p(load);
sem_p(north);
printf("\nC从北往南-过北桥段\n");
//V操作信号量north
sem_v(north);
printf("\nC从北往南-到桥中间\n");
//P操作信号量south
sem_p(south);
printf("\nC从北往南-过南桥段\n");
//V操作信号量south和load
sem_v(south);
sem_v(load);
printf("\nC从北往南-到达南岸\n");
}
/*调用fork函数创建第二个子进程D,其返回值为pid_D*/
pid_D = fork();
/*通过pid_D的值来判断fork函数的返回情况,首先进行出错处理*/
if(pid_D == -1)
{
perror("Fork\n");
}
else if (pid_D == 0) /*返回值为0代表子进程*/
{
//P操作信号量load和north
sem_p(load);
sem_p(north);
printf("\nD从北往南-过北桥段\n");
//V操作信号量north
sem_v(north);
printf("\nD从北往南-到桥中间\n");
//P操作信号量south
sem_p(south);
printf("\nD从北往南-过南桥段\n");
//V操作信号量south和load
sem_v(south);
sem_v(load);
printf("\nD从北往南-到达南岸\n");
}
/*调用fork函数创建第三个子进程E,其返回值为pid_E*/
pid_E = fork();
/*通过pid_E的值来判断fork函数的返回情况,首先进行出错处理*/
if(pid_E == -1)
{
perror("Fork\n");
}
else if (pid_E == 0) /*返回值为0代表子进程*/
{
//P操作信号量load和north
sem_p(load);
sem_p(north);
printf("\nE从北往南-过北桥段\n");
//V操作信号量north
sem_v(north);
printf("\nE从北往南-到桥中间\n");
//P操作信号量south
sem_p(south);
printf("\nE从北往南-过南桥段\n");
//V操作信号量south和load
sem_v(south);
sem_v(load);
printf("\nE从北往南-到达南岸\n");
}
exit(0);
}
Makefile文件。
EXEC = NorthtoSouth SouthtoNorth
OBJS = NorthtoSouth.o SouthtoNorth.o sem_com.o
HEADERS = sem_com.h
CC = gcc
INC = -I.
CFLAGS = ${INC} -g
all {EXEC}
${EXEC} : ${OBJS}
${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS}
${OBJS} : ${HEADERS}
.PHONY : clean
clean :
-rm -f ${OBJS} ${EXEC}
我来回答