我想编写一个简单的程序,在其中可以显示Linux C中的死锁。这是我写的,但是显然这不是正确的主意。我想要一个示例,其中我通过使用信号量而陷入僵局,但无法弄清楚如何解决它。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/wait.h>
#define KEY 19950914
#define FLAG 0666
int main()
{
int stop = 1, semid;
struct sembuf down = { 0, -1, SEM_UNDO };
struct sembuf up = { 0, 1, SEM_UNDO };
semid = semget(KEY, 1, FLAG | IPC_CREAT);
if (semid < 0)
perror("semget"), exit(EXIT_FAILURE);
semctl(semid, 0, SETVAL, 1);
if (fork() == 0)
{
printf("Child is trying to take resources \n");
semop(semid, &down, 1);
printf("Child aquired resources \n");
do{
}while(stop != 0);
exit(EXIT_SUCCESS);
}
wait(NULL);
printf("Parent trying to take resources \n");
semop(semid, &down, 1);
printf("Parent aquired resources \n");
semctl(semid, 0, IPC_RMID, NULL);
exit(EXIT_SUCCESS);
}
术语deadlock专门表示阻塞多个线程或进程以等待彼此持有的资源的情况。因此,您的程序没有“死锁”:是的,一个线程被阻塞等待资源,是的,但是该资源被一个线程保持,该线程被not阻塞等待资源。
单个信号量不会被死锁,除非被滥用。
信号量的初始设置是它为零。
如果您有-5…,但只有3个进程…。您正在滥用信号量。
您获得死锁的唯一方法是,您有一个或多个进程在等待它,但是没有任何进程释放它(无效情况)。如果您拥有一个进程,则该进程必须释放它(或者再次,它被滥用)。
semaphore-deadlock.c
/** Lab Subject :
* Simulate a deadlock situation
*/
#include <stdio.h> // Input/Output
#include <unistd.h> // Time management (usleep)
#include <pthread.h> // Threads management
#include <sys/sem.h> // Semaphores management
#define PERMS 0660 // -rw permissions for group and user
int semId;
int initSem(int semId, int semNum, int initValue) {
return semctl(semId, semNum, SETVAL, initValue);
}
/* An operation list is structured like this :
* { semphore index, operation, flags }
* The operation is an integer value interpreted like this :
* >= 0 : Rise the semaphore value by this value.
* This trigger the awakening of semaphores waiting for a rise.
* == 0 : Wait for the semaphore to be at value 0.
* < 0 : Substract abs(value) to the semaphore.
* If then the semaphore is negative, wait for a rise.
*/
// Try to take a resource, wait if not available
int P(int semId, int semNum) {
// Operation list of 1 operation, taking resource, no flag
struct sembuf operationList[1];
operationList[0].sem_num = semNum;
operationList[0].sem_op = -1;
operationList[0].sem_flg = 0;
return semop(semId, operationList, 1);
}
// Release a resource
int V(int semId, int semNum) {
// Operation list of 1 operation, releasing resource, no flag
struct sembuf operationList[1];
operationList[0].sem_num = semNum;
operationList[0].sem_op = 1;
operationList[0].sem_flg = 0;
return semop(semId, operationList, 1);
}
void* funcA(void* nothing) {
printf("Thread A try to lock 0...\n");
P(semId, 0); // Take resource/semaphore 0 of semID
printf("Thread A locked 0.\n");
usleep(50*1000); // Wait 50 ms
printf("Thread A try to lock 1...\n");
P(semId, 1); // Take resource/semaphore 1 of semID
printf("Thread A locked 1.\n");
V(semId, 0); // Release resource/semaphore 0 of semID
V(semId, 1); // Release resource/semaphore 1 of semID
return NULL;
}
void* funcB(void* nothing) {
printf("Thread B try to lock 1...\n");
P(semId, 1); // Take resource/semaphore 0 of semID
printf("Thread B locked 1.\n");
usleep(5*1000); // Wait 50 ms
printf("Thread B try to lock 0...\n");
P(semId, 0); // Take resource/semaphore 1 of semID
printf("Thread B locked 0.\n");
V(semId, 0); // Release resource/semaphore 0 of semID
V(semId, 1); // Release resource/semaphore 1 of semID
return NULL;
}
// Main function
int main(int argc, char* argv[]) {
int i; // Iterator
// We create a set of 2 semaphores
// ftok generates a key based on the program name and a char value
// This avoid to pick an arbitrary key already existing
semId = semget(ftok(argv[0], 'A'), 2, IPC_CREAT | PERMS);
// Set the semaphore at index 0 to value 1 (= available for use)
initSem(semId, 0, 1);
// Set the semaphore at index 1 to value 1 (= available for use)
initSem(semId, 1, 1);
pthread_t thread[2]; // Array of threads
pthread_create(&thread[0], NULL, funcA, NULL);
pthread_create(&thread[1], NULL, funcB, NULL);
// Wait until threads are all complete
for (i = 0 ; i < 2 ; i++) {
pthread_join(thread[i], NULL);
}
printf("This is not printed in case of deadlock\n");
// Free the semaphores
semctl(semId, 0, IPC_RMID, 0);
semctl(semId, 1, IPC_RMID, 0);
return 0;
}