POSIX 信号量和 pthread 问题
POSIX semaphore and pthread issue
我正在使用 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
这里的整个前提对我来说似乎有点奇怪,因为我从未见过任何会导致任何线程阻塞的争用。尽管如此,我确实看到了一个会导致程序崩溃的特定缺陷。
有 8 个 "plates"(互斥锁)和 10 个 "customers",这是您线程中的值 "n"。
pthread_mutex_lock(&plates[n]);
将在 n=7 之前正常工作,然后在 n=8 时崩溃,因为它指向无效内存。
此外,pthread 入口函数的正确原型是 void *function(void* arg)
(不是 int
)。您必须将值作为 void*
传递,然后将其在本地转换回 int
,如果这是您想要的 - 但请注意,这也可能会产生有关截断的编译器警告,因为 int
是在许多平台上小于 void*
。
畸形/未定义行为
正如我在评论中所述,您的程序中至少有两个未定义行为的来源:
您试图将 eat()
用作线程启动函数,但它的类型不正确。线程启动函数必须接受类型为 void *
和 return void *
的单个参数,但 eat()
的参数类型为 int
。由于参数类型不匹配,您对 pthread_create()
的调用具有未定义的行为。在某种程度上 pthread_create()
可以被解释为调用指向的函数,该调用也将有其自己的未定义行为。
您分派了 10 个客户线程,每个线程都尝试锁定不同的板互斥锁,但只有 8 个板互斥锁可用。因此,如果您实际上假设 eat()
接收到您似乎希望它执行的参数值,那么您必须超出 plate mutex 数组的范围。即使您认为溢出会导致操纵可访问内存(是否确实未定义),该内存肯定还没有通过 pthread_mutex_init()
初始化以用作互斥锁。
可能其中之一或两者都对您的段错误负责。
奇怪的行为
您创建并使用了一堆您不需要的同步对象。 eat()
函数的整个主体由信号量 server_sem
保护,并且您使用该信号量的方式可确保永远不会有超过一个线程执行该函数。因此,互斥量和其他信号量内部的所有使用都没有实际意义——永远不会有任何其他同步对象的争用。
正如 eat()
所写,您让每个客户线程依次锁定每个 table 信号量,并在每个信号量锁的保护下锁定一个板互斥量。那么,就您尝试建模的内容而言,每位顾客吃两次,每次吃一次 table,但来自同一个盘子。
每个客户线程使用不同的印版(或尝试这样做),因此不存在印版争用。没有争用,就不需要互斥锁来保护板访问,即使服务器信号量没有也防止争用。
总的来说,我不清楚您要建模的交互是什么。如果您也不清楚这一点,那么这可能是您遇到困难的原因之一。我倾向于猜测,也许您希望另一个线程代表一个服务器,该服务器将与客户线程合作,将它们分配给可用的席位。即使那样,我也不确定我是否看到了板互斥锁的用途。
我正在使用 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
这里的整个前提对我来说似乎有点奇怪,因为我从未见过任何会导致任何线程阻塞的争用。尽管如此,我确实看到了一个会导致程序崩溃的特定缺陷。
有 8 个 "plates"(互斥锁)和 10 个 "customers",这是您线程中的值 "n"。
pthread_mutex_lock(&plates[n]);
将在 n=7 之前正常工作,然后在 n=8 时崩溃,因为它指向无效内存。
此外,pthread 入口函数的正确原型是 void *function(void* arg)
(不是 int
)。您必须将值作为 void*
传递,然后将其在本地转换回 int
,如果这是您想要的 - 但请注意,这也可能会产生有关截断的编译器警告,因为 int
是在许多平台上小于 void*
。
畸形/未定义行为
正如我在评论中所述,您的程序中至少有两个未定义行为的来源:
您试图将
eat()
用作线程启动函数,但它的类型不正确。线程启动函数必须接受类型为void *
和 returnvoid *
的单个参数,但eat()
的参数类型为int
。由于参数类型不匹配,您对pthread_create()
的调用具有未定义的行为。在某种程度上pthread_create()
可以被解释为调用指向的函数,该调用也将有其自己的未定义行为。您分派了 10 个客户线程,每个线程都尝试锁定不同的板互斥锁,但只有 8 个板互斥锁可用。因此,如果您实际上假设
eat()
接收到您似乎希望它执行的参数值,那么您必须超出 plate mutex 数组的范围。即使您认为溢出会导致操纵可访问内存(是否确实未定义),该内存肯定还没有通过pthread_mutex_init()
初始化以用作互斥锁。
可能其中之一或两者都对您的段错误负责。
奇怪的行为
您创建并使用了一堆您不需要的同步对象。 eat()
函数的整个主体由信号量 server_sem
保护,并且您使用该信号量的方式可确保永远不会有超过一个线程执行该函数。因此,互斥量和其他信号量内部的所有使用都没有实际意义——永远不会有任何其他同步对象的争用。
正如 eat()
所写,您让每个客户线程依次锁定每个 table 信号量,并在每个信号量锁的保护下锁定一个板互斥量。那么,就您尝试建模的内容而言,每位顾客吃两次,每次吃一次 table,但来自同一个盘子。
每个客户线程使用不同的印版(或尝试这样做),因此不存在印版争用。没有争用,就不需要互斥锁来保护板访问,即使服务器信号量没有也防止争用。
总的来说,我不清楚您要建模的交互是什么。如果您也不清楚这一点,那么这可能是您遇到困难的原因之一。我倾向于猜测,也许您希望另一个线程代表一个服务器,该服务器将与客户线程合作,将它们分配给可用的席位。即使那样,我也不确定我是否看到了板互斥锁的用途。