【发布时间】:2015-11-22 09:47:32
【问题描述】:
我正在尝试为我的操作系统类开发一个项目,并且在使用 pthread 时遇到了 SegFault,但我不确定是什么导致了问题。
至于程序,我正在尝试完成以下程序:
南非克鲁格国家公园某处有一个深峡谷,一根绳索横跨峡谷。 狒狒可以通过在绳索上双手交叉摆动来穿越峡谷,但如果两只相反方向的狒狒在中间相遇,它们会打架并摔死。此外,绳索的强度仅足以容纳三只狒狒。如果绳子上同时有更多的狒狒,它就会断裂。假设我们可以教狒狒使用信号量,我们想设计一个具有以下属性的同步方案。
- 一旦狒狒开始穿越,它就可以保证到达另一边而不会碰到另一边的狒狒。
- 绳子上的狒狒永远不会超过三只。狒狒穿越绳索的顺序应保持;即他们进入绳索的顺序应该是他们离开绳索的顺序。
- 持续不断的狒狒流向一个方向穿越不应无限期地阻止狒狒向另一方向前进(不会挨饿)。解决此要求以保留 FIFO 顺序。也就是说,试图向左/向右穿越的狒狒比试图向相反方向穿越的狒狒先到达绳索。
基本上,我正在读取一个文本文件,然后模拟一个 FIFO 系统,其中一些猴子正试图穿过索桥。 奇怪的是我能够让程序运行几次,但它经常会导致 SegFault。
pthread_create(&eastern[i],NULL,(void *) &east_side,(void *)&id[i]);
pthread_create(&western[i],NULL,(void *) &west_side,(void *)&id[i]);
east_side 和 west_side 位于下方。
void* east_side(void*arg)
{
int baboon = *(int*)arg;
int on_rope;
sem_wait(&deadlock_protection);
sem_wait(&east_mutex);
east++;
if (east == 1)
{
sem_wait(&rope);
printf("Baboon %d: waiting\n", baboon);
}
sem_post(&east_mutex);
sem_post(&deadlock_protection);
sem_wait(&counter);
sem_getvalue(&counter, &on_rope);
printf("Baboon %d: Cross rope request granted (Current crossing: left to right, Number of baboons on rope: %d)\n", baboon,3-on_rope);
sleep(travel_time);
sem_getvalue(&counter, &on_rope);
printf("Baboon %d: Exit rope (Current crossing: left to right, Number of baboons on rope: %d)\n", baboon, 2-on_rope);
sem_post(&counter);
sem_wait(&east_mutex);
east--;
if (east == 0)
sem_post(&rope);
sem_post(&east_mutex);
}
//thread handling west to east travel
void* west_side(void*arg)
{
int baboon = *(int*)arg;
int on_rope;
sem_wait(&deadlock_protection);
sem_wait(&west_mutex);
west++;
if (west == 1)
{
sem_wait(&rope);
printf("Baboon %d: waiting\n", baboon);
}
sem_post(&west_mutex);
sem_post(&deadlock_protection);
sem_wait(&counter);
sem_getvalue(&counter, &on_rope);
printf("Baboon %d: Cross rope request granted (Current crossing: right to left, Number of baboons on rope: %d)\n", baboon, 3-on_rope);
sleep(travel_time);
sem_getvalue(&counter, &on_rope);
printf("Baboon %d: Exit rope (Current crossing: right to left, Number of baboons on rope: %d)\n", baboon, 2-on_rope);
sem_post(&counter);
sem_wait(&west_mutex);
west--;
if (west == 0)
sem_post(&rope);
sem_post(&west_mutex);
}
我在
的纯文本文件中使用示例输入L,R,R,R,R,R,L,L,R
这将创建输出:
sh-4.3$ 主输入.txt 5
输入是
L R R R R R L L R
狒狒 1:请求越过绳索(从左到右)
狒狒 1:等待
狒狒 1:已批准交叉绳索请求(当前交叉:从左到右,绳索上的狒狒数量:1)
狒狒 2:请求越过绳索(从右到左)
狒狒 3:请求越过绳索(从右到左)
狒狒 4:请求越过绳索(从右到左)
狒狒 5:请求越过绳索(从右到左)
狒狒1:出口绳索(当前穿越:从左到右,绳索上的狒狒数量:0)
狒狒 2:等待
狒狒 2:已批准交叉绳索请求(当前交叉:从右到左,绳索上的狒狒数量:1)
狒狒 3:已批准交叉绳索请求(当前交叉:从右到左,绳索上的狒狒数量:2)
狒狒 4:已批准交叉绳索请求(当前交叉:从右到左,绳索上的狒狒数量:3)
狒狒 6:请求越过绳索(从右到左)
狒狒 7:请求越过绳索(从左到右)
狒狒 8:请求越过绳索(从左到右)
狒狒 9:请求越过绳索(从右到左)
分段错误(核心转储)
我已经包含了整个文件,以防问题实际上不是我认为的问题所在。
/*include header files*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <semaphore.h>
//#include <stdbool.h>
//compile with command
//gcc -o main *.c -lpthread -lrt
/*semaphores*/
sem_t rope;
sem_t east_mutex;
sem_t west_mutex;
sem_t deadlock_protection;
sem_t counter;
/*global variables*/
int east = 0;
int west = 0;
int travel_time;
/*function prototypes*/
void crossing(int x);
void* east_side(void*);
void* west_side(void*);
/*main function*/
int main(int argc, char *argv[])
{
char c;
int baboonCnt=0;
char temp[100];
sem_init(&rope,0,1); //ensure mutual exclusion on rope ownership
sem_init(&east_mutex,0,1); //east side on travel
sem_init(&west_mutex,0,1); //west side on travel
sem_init(&deadlock_protection,0,1); //used to prevent deadlocks while using semaphores
sem_init(&counter,0,3); //ensure only 3 baboons are allowed on the rope
//ensure all input arguements are entered
if ( argc == 3 )
{
travel_time = atoi(argv[2]);
FILE *file;
int baboonCnt=0;
if (file = fopen(argv[1], "r") )
{
while((c=getc(file))!=EOF)
{
if(c == 'L'|| c == 'R')
{
temp[baboonCnt] = c;
baboonCnt++;
}
}
}
else
{
printf("Unable to read data from the input file.");
return 0;
}
printf("The input is\n");
int j=0;
for(j;j<baboonCnt;++j)
{
printf("%c ",temp[j]);
}
printf("\n");
int id[baboonCnt];
pthread_t eastern[baboonCnt],western[baboonCnt];
int i=0;
for(i;i<baboonCnt;++i)
{
sleep(1);
if(temp[i]=='L')
{
id[i] = i+1;
printf("Baboon %d: Request to cross rope (left to right)\n", i+1);
pthread_create(&eastern[i],NULL,(void *) &east_side,(void *)&id[i]);
}
else if(temp[i]=='R')
{
id[i] = i+1;
printf("Baboon %d: Request to cross rope (right to left)\n", i+1);
pthread_create(&western[i],NULL,(void *) &west_side,(void *)&id[i]);
}
}
int k=0;
printf("before k loop");
for(k;k<baboonCnt;++k)
{
pthread_join(eastern[k],NULL);
printf("eastern",k);
pthread_join(western[k],NULL);
printf("western %d",k);
}
//destroy all semaphores
sem_destroy (&rope);
sem_destroy (&east_mutex);
sem_destroy (&west_mutex);
sem_destroy (&deadlock_protection);
sem_destroy (&counter);
return 0;
}
else
{
printf("Proper command line usage is: \n<name> <filename> <cross time>\n");
}
}
//thread handling the east to west to travel
void* east_side(void*arg)
{
int baboon = *(int*)arg;
int on_rope;
sem_wait(&deadlock_protection);
sem_wait(&east_mutex);
east++;
if (east == 1)
{
sem_wait(&rope);
printf("Baboon %d: waiting\n", baboon);
}
sem_post(&east_mutex);
sem_post(&deadlock_protection);
sem_wait(&counter);
sem_getvalue(&counter, &on_rope);
printf("Baboon %d: Cross rope request granted (Current crossing: left to right, Number of baboons on rope: %d)\n", baboon,3-on_rope);
sleep(travel_time);
sem_getvalue(&counter, &on_rope);
printf("Baboon %d: Exit rope (Current crossing: left to right, Number of baboons on rope: %d)\n", baboon, 2-on_rope);
sem_post(&counter);
sem_wait(&east_mutex);
east--;
if (east == 0)
sem_post(&rope);
sem_post(&east_mutex);
}
//thread handling west to east travel
void* west_side(void*arg)
{
int baboon = *(int*)arg;
int on_rope;
sem_wait(&deadlock_protection);
sem_wait(&west_mutex);
west++;
if (west == 1)
{
sem_wait(&rope);
printf("Baboon %d: waiting\n", baboon);
}
sem_post(&west_mutex);
sem_post(&deadlock_protection);
sem_wait(&counter);
sem_getvalue(&counter, &on_rope);
printf("Baboon %d: Cross rope request granted (Current crossing: right to left, Number of baboons on rope: %d)\n", baboon, 3-on_rope);
sleep(travel_time);
sem_getvalue(&counter, &on_rope);
printf("Baboon %d: Exit rope (Current crossing: right to left, Number of baboons on rope: %d)\n", baboon, 2-on_rope);
sem_post(&counter);
sem_wait(&west_mutex);
west--;
if (west == 0)
sem_post(&rope);
sem_post(&west_mutex);
}
【问题讨论】:
-
调试 segfaults 时,gdb(或类似的调试器)绝对是无价之宝,而且学习起来并不难——还有很多可用的教程:google.com/search?q=gdb+tutorial 还有——你会通过发布最小、完整且可验证的示例可能会得到更好的答案 - 更多信息请点击此处:stackoverflow.com/help/mcve
-
+1 获得有关使用调试器的建议 - 从长远来看,如果您自己做硬码而不是求助于基本调试,您将学到更多。如果您已经用尽了调试方法,那么至少您应该准确地告诉我们您的程序的当前行为是什么——您的程序中有很多调试语句(一件好事),所以准确地分享什么是有意义的输出导致崩溃。如果我们要尝试重现问题,我们还需要知道确切的输入。
-
一个问题:进行
pthead_create调用的循环不会填充western和easternpid 数组的每个索引。也就是说,这些数组在 pid 值是垃圾的地方存在间隙。然而,您的pthread_join循环尝试使用这两个数组中的每个索引。也就是说,一些pthread_join调用被传递垃圾值。 -
@kaylum 好的,感谢您的建议。我编辑了一些帖子以反映您的建议。至于 pthread_create 循环,我将看看如何更改它,看看是否有帮助。
-
@kaylum 这似乎是我的问题的根源。一旦我对该问题进行了修复,segFault 问题似乎就消失了。我需要尝试继续测试它以确保没有问题,但乍一看,它似乎有效。