用 C 语言编写二个程序利用 UNIX System V 信号量机制有意造成死锁的发生观察死锁现象。
程序一:deadlock1.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define SEMKEY 1234
int main()
{
int semid, pid, i;
struct sembuf sembuf;
// 创建信号量集
if ((semid = semget(SEMKEY, 2, IPC_CREAT | 0666)) == -1)
{
perror("semget error");
exit(1);
}
// 初始化信号量集
semctl(semid, 0, SETVAL, 1);
semctl(semid, 1, SETVAL, 1);
// 创建子进程
if ((pid = fork()) == -1)
{
perror("fork error");
exit(1);
}
if (pid == 0) // 子进程
{
printf("Child process is waiting for semaphore 0...\n");
sembuf.sem_num = 0;
sembuf.sem_op = -1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) == -1)
{
perror("semop error");
exit(1);
}
printf("Child process got semaphore 0.\n");
sleep(2);
printf("Child process is waiting for semaphore 1...\n");
sembuf.sem_num = 1;
sembuf.sem_op = -1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) == -1)
{
perror("semop error");
exit(1);
}
printf("Child process got semaphore 1.\n");
exit(0);
}
else // 父进程
{
printf("Parent process is waiting for semaphore 1...\n");
sembuf.sem_num = 1;
sembuf.sem_op = -1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) == -1)
{
perror("semop error");
exit(1);
}
printf("Parent process got semaphore 1.\n");
sleep(2);
printf("Parent process is waiting for semaphore 0...\n");
sembuf.sem_num = 0;
sembuf.sem_op = -1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) == -1)
{
perror("semop error");
exit(1);
}
printf("Parent process got semaphore 0.\n");
exit(0);
}
return 0;
}
程序二:deadlock2.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define SEMKEY 1234
int main()
{
int semid, pid, i;
struct sembuf sembuf[2];
// 创建信号量集
if ((semid = semget(SEMKEY, 2, IPC_CREAT | 0666)) == -1)
{
perror("semget error");
exit(1);
}
// 初始化信号量集
semctl(semid, 0, SETVAL, 1);
semctl(semid, 1, SETVAL, 1);
// 创建子进程
if ((pid = fork()) == -1)
{
perror("fork error");
exit(1);
}
if (pid == 0) // 子进程
{
printf("Child process is waiting for semaphore 0 and 1...\n");
sembuf[0].sem_num = 0;
sembuf[0].sem_op = -1;
sembuf[0].sem_flg = SEM_UNDO;
sembuf[1].sem_num = 1;
sembuf[1].sem_op = -1;
sembuf[1].sem_flg = SEM_UNDO;
if (semop(semid, sembuf, 2) == -1)
{
perror("semop error");
exit(1);
}
printf("Child process got semaphore 0 and 1.\n");
exit(0);
}
else // 父进程
{
printf("Parent process is waiting for semaphore 0 and 1...\n");
sembuf[0].sem_num = 1;
sembuf[0].sem_op = -1;
sembuf[0].sem_flg = SEM_UNDO;
sembuf[1].sem_num = 0;
sembuf[1].sem_op = -1;
sembuf[1].sem_flg = SEM_UNDO;
if (semop(semid, sembuf, 2) == -1)
{
perror("semop error");
exit(1);
}
printf("Parent process got semaphore 0 and 1.\n");
exit(0);
}
return 0;
}
编译运行:
$ gcc deadlock1.c -o deadlock1
$ gcc deadlock2.c -o deadlock2
$ ./deadlock1
Parent process is waiting for semaphore 1...
Child process is waiting for semaphore 0...
Child process got semaphore 0.
Parent process got semaphore 1.
Parent process is waiting for semaphore 0...
程序一中,父进程和子进程分别等待对方持有的信号量,因此会发生死锁。
$ ./deadlock2
Parent process is waiting for semaphore 0 and 1...
Child process is waiting for semaphore 0 and 1...
程序二中,父进程和子进程都同时等待两个信号量,因此也会发生死锁。
如果出现死锁,可以使用 ipcs 命令查看系统中的信号量情况,使用 ipcrm 命令删除不需要的信号量
原文地址: https://www.cveoy.top/t/topic/eGzl 著作权归作者所有。请勿转载和采集!