首页 文章

使用pthreads时SegFault

提问于
浏览
0

我正在尝试为我的操作系统类工作,我在使用pthreads时遇到了SegFault,但我不确定是什么导致了这个问题 .

至于该计划,我正在尝试完成以下计划:

南非克鲁格国家公园(Kruger National Park)的某处有一个深峡谷,还有一根横跨峡谷的绳索 . 狒狒可以通过在绳子上手动摆动来穿过峡谷,但如果两只相反方向的狒狒在中间相遇,他们就会战斗并摔死 . 此外,绳索仅足以容纳三只狒狒 . 如果绳子上同时有更多的狒狒,它就会破裂 . 假设我们可以教狒狒使用信号量,我们想设计一个具有以下属性的同步方案 . 一旦狒狒开始越过,它就会保证到另一边而不会跑到另一边的狒狒身边 . 绳子上永远不会有三个以上的狒狒 . 应保留穿越绳索的狒狒的顺序;即,它们进入绳索的顺序应该是它们离开绳索的顺序 . 在一个方向上持续不断的狒狒流不应该禁止狒狒无限期地走向另一个方向(没有饥饿) . 解决此要求,以便保留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 $ main input.txt 5
输入是
L R R R R R 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);
}

2 回答

  • 0

    运行valgrind几乎是imediate来检测你的错误:

    ==10217== Use of uninitialised value of size 8
    ==10217==    at 0x4E39241: pthread_join (in /usr/lib64/libpthread-2.18.so)
    ==10217==    by 0x400E64: main (example.c:103)
    

    第103行是 pthread_join(eastern[k],NULL); ; valgrind强调东部阵列是在没有设置的情况下读取的 .

    您的阵列未得到满足,您可以访问未设置的元素 . 你可以用这种方式修改join循环:

    for(k;k<baboonCnt;++k)
    {
        if(temp[k]=='L') {
                pthread_join(eastern[k],NULL);
                printf("eastern %d\n",k);
        }
        else if(temp[k]=='R') {
                pthread_join(western[k],NULL);
                printf("western %d\n",k);
        }
    }
    
  • 0

    正如这个帖子中的其他人所提到的那样,我在我的代码中遇到了一个错误,我试图访问那些尚未正确初始化的数组元素 . 我在这里总结了我对这篇文章的更改 . 感谢@kaylum帮助我得出这个结论 .

    这些数组访问发生在这里:

    for(k;k<baboonCnt;++k)
        {
    
            pthread_join(eastern[k],NULL);
            printf("eastern",k);
            pthread_join(western[k],NULL); 
            printf("western %d",k);         
        }
    

    不恰当的初始化发生在行中

    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]);
            }
        }
    

    这两组代码是造成执行问题的原因,包括我遇到的SegFault . 修改初始化部分而不是创建2个独立的ID数组,一个引用东狒狒,另一个引用西狒狒,而不是简单地将所有ID保存在一个组中,这是使程序工作的关键 . 调整id密钥存储方法后,还需要修改pthread_join循环,以便它们正确访问数组 .

    这是修改后的初始化部分:

    int eastcnt=0, westcnt=0, eastid[eastBab], westid[westBab], i=0;
        for(i;i<baboonCnt;++i)
          {
            sleep(1);
            if(temp[i]=='L')
              {
            eastid[eastcnt]=i;
            printf("Baboon %d wants to cross left to right\n",i);
            pthread_create(&eastern[eastcnt],NULL, (void *) &east_side,(void *) &eastid[eastcnt] );
            ++eastcnt;
              }
            else if(temp[i]=='R')
              {
            westid[westcnt]=i;
            printf("Baboon %d wants to cross right to left\n",i);
            pthread_create(&western[westcnt],NULL, (void *) &west_side,(void *) &westid[westcnt] );
            ++westcnt;
              }
          }
    

    和修改后的pthread_join循环

    int k =0;
        for(k;k<westBab;++k)
        {
            pthread_join(western[k],NULL); 
        }
        k=0;
        for(k;k<eastBab;++k)
        {
            pthread_join(eastern[k],NULL); 
        }
    

    在进行了上述更改以及一些常规清理后,整个程序都符合规范 .

相关问题