C POSIX信号量和pthread问题

C POSIX信号量和pthread问题,c,pthreads,posix,semaphore,C,Pthreads,Posix,Semaphore,我正在使用POSIX库练习信号量。我试图通过一个信号量(代表一台服务器)传递线程(代表客户),该信号量让8个人坐在两张桌子旁(每个桌子都由Semphores控制)。我认为罪魁祸首是解锁和锁定多个信号量的顺序,但我似乎无法确定非法指令(内核转储)错误的来源 编辑 -互斥体初始化的逆序和创建线程循环 -将return NULL添加到eat()的末尾: #包括 #包括 #包括 #包括 sem_t server_sem; int服务器共享; int server_ret; int server_coun

我正在使用POSIX库练习信号量。我试图通过一个信号量(代表一台服务器)传递线程(代表客户),该信号量让8个人坐在两张桌子旁(每个桌子都由Semphores控制)。我认为罪魁祸首是解锁和锁定多个信号量的顺序,但我似乎无法确定非法指令(内核转储)错误的来源

编辑 -互斥体初始化的逆序和创建线程循环 -将return NULL添加到eat()的末尾:

#包括
#包括
#包括
#包括
sem_t server_sem;
int服务器共享;
int server_ret;
int server_count=10;
sem_t tablea_sem;
int tablea_pshared;
国际表格;
int tablea_计数=4;
sem_t表B_sem;
int表b_pshared;
int tableb_ret;
int tableb_计数=4;
//server_ret=serm_open(“serverSem”,O|u CREAT | O|u EXCL,0644,server_count);
int客户_计数=10;
pthread_t客户[10];
//p螺纹板[8]
内板计数=8;
pthread_mutex_t plates[8];
空*吃(整数n){
sem_wait(&server_sem);
printf(“坐在A桌旁\n”);
//解锁表a信号量
sem_wait(表a_sem);
//解锁
pthread_mutex_lock(&plates[n]);
printf(“客户%d正在吃饭\n”,n);
睡眠(5);
pthread_mutex_unlock(&plates[n]);
printf(“客户%d已吃完\n”,n);
//sem_post(服务器_sem);
sem_post(表A_sem);
printf(“坐在A桌旁\n”);
//解锁表b信号量
sem_wait(表b_sem);
//解锁
//sem_wait(&server_sem);
pthread_mutex_lock(&plates[n]);
printf(“客户%d正在吃饭\n”,n);
睡眠(5);
pthread_mutex_unlock(&plates[n]);
printf(“客户%d已吃完\n”,n);
sem_post(表B_sem);
sem_post(服务器_sem);
返回NULL;
}
int main(){
server\u ret=sem\u init(&server\u sem,1,server\u count);
tablea_ret=sem_init(&tablea_sem,1,tablea_计数);
tableb_ret=sem_init(&tableb_sem,1,tableb_count);
//customer=(pthread_t[10]*)malloc(sizeof(customer));
printf(“启动线程,信号量已解锁。\n”);
int i;

对于(i=0;i而言,这里的整个前提对我来说似乎有点奇怪,因为我从未看到任何会导致任何线程阻塞的争用。尽管如此,我确实看到了一个会导致程序崩溃的特定缺陷

有8个“板”(互斥)和10个“客户”,这是线程中的值“n”

pthread\u mutex\u lock(&plates[n]);

将在n=7时正常工作,然后在n=8时崩溃,因为它指向无效内存


另外-pthread entry函数的正确原型是
void*函数(void*arg)
(而不是
int
)。您必须以
void*
的形式传递值,然后在本地将其强制转换回
int
,如果这是您想要的-但请注意,这也可能会产生编译器关于截断的警告,因为在许多平台上
int
小于
void*

这里的整个前提对我来说似乎有点奇怪,因为我从来没有看到过任何上下文ntion,它将导致任何线程阻塞。尽管如此,我确实看到一个特定的缺陷,它将导致程序崩溃

有8个“板”(互斥)和10个“客户”,这是线程中的值“n”

pthread\u mutex\u lock(&plates[n]);

将在n=7时正常工作,然后在n=8时崩溃,因为它指向无效内存

另外-pthread entry函数的正确原型是
void*函数(void*arg)
(而不是
int
)。您必须将值作为
void*
传递,然后在本地将其强制转换回
int
,如果这是您想要的-但请注意,这也可能会产生编译器关于截断的警告,因为在许多平台上
int
小于
void*

畸形/未定义行为 正如我在评论中所描述的,您的程序中至少有两个未定义行为的来源:

  • 您试图将
    eat()
    用作线程启动函数,但它的类型不正确。线程启动函数必须接受类型为
    void*
    的单个参数并返回
    void*
    ,但
    eat()
    的参数类型为
    int
    。您对
    pthread\u create()的调用由于参数类型不匹配,
    具有未定义的行为。如果可以将
    pthread_create()
    解释为调用指向函数,则该调用也将具有自己的未定义行为

  • 您调度了十个客户线程,每个线程都试图锁定不同的板互斥锁,但只有八个板互斥锁可用。因此,如果您确实假设
    eat()为
    接收您似乎希望它执行的参数值。即使您认为溢出会导致操纵可访问内存(无论它是否实际执行,但尚未定义),该内存肯定尚未通过
    pthread\u mutex\u init()
    初始化以用作互斥对象

  • 可能是其中一个或两个原因导致了您的SEG故障

    古怪的行为 您可以创建并使用一组不需要的同步对象
    函数受信号量
    服务器\u sem
    保护,使用该信号量的方式确保执行该函数的线程不会超过一个。因此,互斥体和其他信号量内部的所有使用都是没有意义的——对于那些其他同步对象永远不会有任何争用

    在编写
    eat()
    时,您让每个客户线程依次锁定每个表信号量,并在每个信号量的保护下锁定一个板互斥锁

    每个客户线程使用不同的板(或尝试使用不同的板),因此没有对板的争用。没有争用,就不需要
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    
    sem_t server_sem;
    int server_pshared;
    int server_ret;
    int server_count = 10;
    
    sem_t tablea_sem;
    int tablea_pshared;
    int tablea_ret;
    int tablea_count = 4;
    
    sem_t tableb_sem;
    int tableb_pshared;
    int tableb_ret;
    int tableb_count = 4;
    
    
    
    //server_ret = serm_open("serverSem", O_CREAT | O_EXCL, 0644, server_count);
    
    int customer_count = 10;
    pthread_t customer[10];
    //pthread_t plates[8]
    
    int plate_count = 8;
    pthread_mutex_t plates[8];
    
    
    void *eat(int n) {
       sem_wait(&server_sem);
       printf("Sitting down at Table A\n");
       //unlock table a semaphore
       sem_wait(&tablea_sem);
    
       //unlock 
    
       pthread_mutex_lock(&plates[n]);
       printf("Customer %d is eating\n", n);
       sleep(5);
       pthread_mutex_unlock(&plates[n]);
       printf("Customer %d is finished eating\n", n);
       //sem_post(&server_sem);
    
       sem_post(&tablea_sem);
    
       printf("Sitting down at Table A\n");
       //unlock table b semaphore
       sem_wait(&tableb_sem);
    
       //unlock 
       //sem_wait(&server_sem);
       pthread_mutex_lock(&plates[n]);
       printf("Customer %d is eating\n", n);
       sleep(5);
       pthread_mutex_unlock(&plates[n]);
       printf("Customer %d is finished eating\n", n);
    
    
       sem_post(&tableb_sem);
    
       sem_post(&server_sem);
       return NULL;
    }
    
    int main() {
    
    
       server_ret = sem_init(&server_sem, 1, server_count);
       tablea_ret = sem_init(&tablea_sem, 1, tablea_count);
       tableb_ret = sem_init(&tableb_sem, 1, tableb_count);
    
       //customer = (pthread_t[10] *)malloc(sizeof(customer));
    
       printf ("starting thread, semaphore is unlocked.\n");
    
       int i;
    
       for(i=0;i<plate_count;i++)
          pthread_mutex_init(&plates[i],NULL);
    
       for (i=0;i<customer_count;i++)
          pthread_create(&customer[i],NULL,(void *)eat,(void *)i);
    
    
       //for(i=0;i<plate_count;i++)
       //   pthread_mutex_init(&plates[i],NULL);
    
    
       for(i=0;i<customer_count;i++)
          pthread_join(customer[i],NULL);
    
       for(i=0;i<plate_count;i++)
          pthread_mutex_destroy(&plates[i]);
    
       return 0;
       }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <semaphore.h>
    #include <stdint.h>
    
    
    sem_t server_sem;
    int server_pshared;
    int server_ret;
    int server_count = 10;
    
    sem_t tablea_sem;
    int tablea_pshared;
    int tablea_ret;
    int tablea_count = 4;
    
    sem_t tableb_sem;
    int tableb_pshared;
    int tableb_ret;
    int tableb_count = 4;
    
    
    
    //server_ret = serm_open("serverSem", O_CREAT | O_EXCL, 0644, server_count);
    
    int customer_count = 10;
    pthread_t customer[10];
    //pthread_t plates[8]
    
    int plate_count = 8;
    pthread_mutex_t plates[8];
    
    
    //void *eat(int n) {
    void *eat(void *i) {
    
        //int n = *((int *) i);
        int n = (int)(intptr_t) i;
        //printf("Customer %d is eating", m);
        sem_wait(&server_sem);
    
    
        int j;
    
        for (j = 0; j<4; j++) {
          sem_wait(&tablea_sem);
          pthread_mutex_lock(&plates[j]);
          printf("Customer %d is eating\n", n);
          printf("Plate %d is eaten\n", j);
          sleep(5);
          pthread_mutex_unlock(&plates[j]);
          printf("Customer %d is finished eating\n", n);
          sem_post(&tablea_sem);
        }
        for (j = 4; j<8; j++) {
          sem_wait(&tableb_sem);
          pthread_mutex_lock(&plates[j]);
          printf("Customer %d is eating\n", n);
          printf("Plate %d is eaten\n", j);
          sleep(5);
          pthread_mutex_unlock(&plates[j]);
          printf("Customer %d is finished eating\n", n);
          sem_post(&tableb_sem);
        }
        j--;
    
    
        sem_post(&server_sem);
    
    
    
        return (NULL);
    
    
    }
    
    int main() {
    
    
       server_ret = sem_init(&server_sem, 1, server_count);
       tablea_ret = sem_init(&tablea_sem, 1, tablea_count);
       tableb_ret = sem_init(&tableb_sem, 1, tableb_count);
    
       //customer = (pthread_t[10] *)malloc(sizeof(customer));
    
       printf ("starting thread, semaphore is unlocked.\n");
    
       int i;
       int j;
       int k;
    
    
    
    
       for(i=0;i<plate_count;i++) {
          pthread_mutex_init(&plates[i],NULL);
          printf("Creating mutex for plate %d\n", i);
       }
       sem_wait(&server_sem);
       for (j=0;j<customer_count;j++) {
         pthread_create(&customer[j],NULL,(void *)eat,(void *) (intptr_t) j);
       }
    
       for(k=0;k<customer_count;k++) {
          pthread_join(customer[k],NULL);
          printf("Joining thread %d\n", k);
       }
    
    
    
       for(i=0;i<plate_count;i++) {
          pthread_mutex_destroy(&plates[i]);
       }
    
       sem_post(&server_sem);
    
    
       return 0;
       }
    
    niu@niu-vb:~/Documents/CSU_OS$ gcc -pthread -o -g  diner diner4.c
    diner: In function `_fini':
    (.fini+0x0): multiple definition of `_fini'
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crti.o(.debug_info): relocation 0 has invalid symbol index 7
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crti.o(.debug_info): relocation 1 has invalid symbol index 8
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crti.o(.debug_info): relocation 2 has invalid symbol index 9
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crti.o(.debug_ranges): relocation 0 has invalid symbol index 4
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crti.o(.debug_ranges): relocation 1 has invalid symbol index 4
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crti.o(.debug_ranges): relocation 2 has invalid symbol index 5
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crti.o(.debug_ranges): relocation 3 has invalid symbol index 5
    /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o:(.fini+0x0): first defined here
    diner: In function `data_start':
    (.data+0x0): multiple definition of `__data_start'
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 11
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 1 has invalid symbol index 12
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 2 has invalid symbol index 2
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 3 has invalid symbol index 2
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 4 has invalid symbol index 11
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 5 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 6 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 7 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 8 has invalid symbol index 12
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 9 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 10 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 11 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 12 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 13 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 14 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 15 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 16 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 17 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 18 has invalid symbol index 13
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 19 has invalid symbol index 21
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2
    /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o:(.data+0x0): first defined here
    diner: In function `data_start':
    (.data+0x8): multiple definition of `__dso_handle'
    /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o:(.data+0x0): first defined here
    diner:(.rodata+0x0): multiple definition of `_IO_stdin_used'
    /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o:(.rodata.cst4+0x0): first defined here
    diner: In function `_start':
    (.text+0x0): multiple definition of `_start'
    /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o:/build/eglibc-oGUzwX/eglibc-2.19/csu/../sysdeps/x86_64/start.S:118: first defined here
    diner: In function `_init':
    (.init+0x0): multiple definition of `_init'
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crti.o(.debug_line): relocation 0 has invalid symbol index 4
    /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crti.o(.debug_line): relocation 1 has invalid symbol index 5
    /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o:/build/eglibc-oGUzwX/eglibc-2.19/csu/../sysdeps/x86_64/crti.S:64: first defined here
    /tmp/cc8RaCJg.o:(.data+0x0): multiple definition of `server_count'
    diner:(.data+0x10): first defined here
    /tmp/cc8RaCJg.o:(.data+0x4): multiple definition of `tablea_count'
    diner:(.data+0x14): first defined here
    /tmp/cc8RaCJg.o:(.data+0x8): multiple definition of `tableb_count'
    diner:(.data+0x18): first defined here
    /tmp/cc8RaCJg.o:(.data+0xc): multiple definition of `customer_count'
    diner:(.data+0x1c): first defined here
    /tmp/cc8RaCJg.o:(.data+0x10): multiple definition of `plate_count'
    diner:(.data+0x20): first defined here
    /tmp/cc8RaCJg.o: In function `eat':
    diner4.c:(.text+0x0): multiple definition of `eat'
    diner:(.text+0xed): first defined here
    /tmp/cc8RaCJg.o: In function `main':
    diner4.c:(.text+0x184): multiple definition of `main'
    diner:(.text+0x271): first defined here
    /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__'
    diner:(.data+0x28): first defined here
    /usr/bin/ld: error in diner(.eh_frame); no .eh_frame_hdr table will be created.
    collect2: error: ld returned 1 exit status
    niu@niu-vb:~/Documents/CSU_OS$ gdb diner
    GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
    Copyright (C) 2014 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-linux-gnu".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.
    For help, type "help".
    Type "apropos word" to search for commands related to "word"...
    Reading symbols from diner...(no debugging symbols found)...done.
    (gdb) run
    Starting program: /home/niu/Documents/CSU_OS/diner 
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    starting thread, semaphore is unlocked.
    Creating mutex for plate 0
    Creating mutex for plate 1
    Creating mutex for plate 2
    Creating mutex for plate 3
    Creating mutex for plate 4
    Creating mutex for plate 5
    Creating mutex for plate 6
    Creating mutex for plate 7
    [New Thread 0x7ffff77f6700 (LWP 18606)]
    Customer 0 is eating
    [New Thread 0x7ffff6ff5700 (LWP 18607)]
    Customer 1 is eating
    [New Thread 0x7ffff67f4700 (LWP 18608)]
    Customer 2 is eating
    [New Thread 0x7ffff5ff3700 (LWP 18609)]
    Customer 3 is eating
    [New Thread 0x7ffff57f2700 (LWP 18610)]
    [New Thread 0x7ffff4ff1700 (LWP 18611)]
    [New Thread 0x7ffff47f0700 (LWP 18612)]
    [New Thread 0x7ffff3fef700 (LWP 18613)]
    [New Thread 0x7ffff37ee700 (LWP 18614)]
    [New Thread 0x7ffff2fed700 (LWP 18615)]
    Customer 0 is finished eating
    Customer 1 is finished eating
    Customer 2 is finished eating
    Customer 3 is finished eating