linux网络编程之System V 信号量(二)
|
用信号量实现进程互斥示例和解决哲学家就餐问题
一、我们在前面讲进程间通信的时候提到过进程互斥的概念,下面写个程序来模拟一下,程序流程如下图:
即父进程打印字 符O,子进程打印字符X,每次打印一个字符后要sleep 一下,这里要演示的效果是,在打印程序的边界有PV操作,故每个进 程中间sleep 的时间即使时间片轮转到另一进程,由于资源不可用也不会穿插输出其他字符,也就是说O或者X字符都会是成 对出现的,如OOXXOOOOXXXXXXOO.... 程序如下:
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/wait.h>
#define ERR_EXIT(m)
do {
perror(m);
exit(EXIT_FAILURE);
} while(0)
union semun
{
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
};
int semid;
/* pv操作之间的临界区,导致打印的字符一定是成对出现的 */
void print(char op_char)
{
int pause_time;
srand(getpid());
int i;
for (i = 0; i < 10; i++)
{
sem_p(semid);
printf("%c", op_char);
fflush(stdout);
pause_time = rand() % 3;
sleep(pause_time);
printf("%c", op_char);
fflush(stdout);
sem_v(semid);
pause_time = rand() % 2;
sleep(pause_time);
}
}
int main(void)
{
semid = sem_create(IPC_PRIVATE);
sem_setval(semid, 1);
pid_t pid;
pid = fork();
if (pid == -1)
ERR_EXIT("fork");
if (pid > 0)
{
print('o');
wait(NULL);
sem_d(semid);
}
else
{
print('x');
}
return 0;
}
sem_create 等函数参考工具集。在调用semget 时指定key = IPC_PRIVATE,表示创建的是私有的信号集,但具 有亲缘关系的进程是可见的,比如父子进程。输出如下: simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./print ooxxooxxooxxooxxooooooxxooxxooxxooxxxxxx 可以看到输出都是成对出现的字符。 分析一下:semval = 1,假设父进程先被调度执行,父进程先P了一下,此时 semval = 0,子进程在父进程睡眠时间被调度的时候尝试P,semval = -1,然后子进程阻塞了,父进程打印完V了一下,semval = 0,唤醒子进程,子进程的P操作返回,打印字符睡眠后V了一 下,semval = 1。当然在子进程睡眠的时候父进程可能也在尝试P,故就一直循环往复下去。
(编辑:佛山站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


