【发布时间】:2017-10-05 19:09:12
【问题描述】:
我正在使用 POSIX 库练习信号量。我试图通过一个信号量(代表一个服务器)传递线程(代表客户),该信号量让 8 个人坐在两张桌子上(每个都由信号量控制)。我认为罪魁祸首是解锁和锁定多个信号量的顺序,但我似乎无法确定非法指令(核心转储)错误的来源。
已编辑 - 互斥量初始化的逆序和创建线程循环 - 将 return NULL 添加到 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;
}
更新:
我已经接受了一个答案,因为它让我很好地了解了我认为最初的问题。可能仍然存在,只是我对这个话题缺乏理解(轻描淡写)。一些研究(手册页和thread)使我修复了 SO 回答者提到的错误,并尽我所能继续调整。
现在,下面的更新代码已尝试解决已接受的答案。但是,我得到了相同的输出……我还是没有抓住重点吗?
#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;
}
带有 gdb 调试的输出(无断点):
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
【问题讨论】:
-
听起来像功课
-
您在创建线程后初始化互斥锁。
-
@user25976 如果你想保护一个共享值不被多个线程访问,你必须只使用一个互斥锁。所有线程都应该锁定/解锁同一个互斥体。
-
您的
eat()函数类型不适合线程启动函数。线程启动函数的单个参数必须具有类型void *,但eat()的参数是int。你的编译器应该警告你这一点。在任何情况下,未定义的行为都源于使用不同于函数形式参数类型的实际参数调用函数。 -
此外,您有 10 个客户和 8 个盘子。如果
eat()尽管存在参数类型问题,但仍按预期工作,则您尝试为每个客户锁定与 customer 编号相对应的 plate 互斥锁。这会访问不存在的板互斥体。
标签: c pthreads posix semaphore