linux理发师多线程问题
Linux下多线程死循环调试

3 Thread 47057194060048 (LWP 11072) 0x00002acc4a406fc2 in select () from /lib/libc.so.6
ovtsvn@ovtsvn:~/MASS4/src/icdn/src$ 然后top命令查看线程信息:
top -H -p 11065
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
#3 0x00002acc4a40d6dd in clone () from /lib/libc.so.6
#4 0x0000000000000000 in ?? (ห้องสมุดไป่ตู้
来看一下101行的代码:
(gdb) l
96 }
97
98 int CSendFile::SendFile(const string& pathname)
#1 0x000000000040592e in CIcdn::TaskThread (pParam=0x7fff617eafe0) at ../src/cicdn.cpp:128
#2 0x00002acc4a90b73a in start_thread () from /lib/libpthread.so.0
at ../src/csendfile.cpp:101
101 while(1)
(gdb)
bt一下:
(gdb) bt
#0 CSendFile::SendFile (this=0x2acc5d4aff40, pathname=@0x2acc5d4afee0) at ../src/csendfile.cpp:101
linux多线程编程详解教程(线程通过信号量实现通信代码)

linux多线程编程详解教程(线程通过信号量实现通信代码)线程按照其调度者可以分为⽤户级线程和核⼼级线程两种。
(1)⽤户级线程主要解决的是上下⽂切换的问题,它的调度算法和调度过程全部由⽤户⾃⾏选择决定,在运⾏时不需要特定的内核⽀持。
在这⾥,操作系统往往会提供⼀个⽤户空间的线程库,该线程库提供了线程的创建、调度、撤销等功能,⽽内核仍然仅对进程进⾏管理。
如果⼀个进程中的某⼀个线程调⽤了⼀个阻塞的系统调⽤,那么该进程包括该进程中的其他所有线程也同时被阻塞。
这种⽤户级线程的主要缺点是在⼀个进程中的多个线程的调度中⽆法发挥多处理器的优势。
(2)这种线程允许不同进程中的线程按照同⼀相对优先调度⽅法进⾏调度,这样就可以发挥多处理器的并发优势。
现在⼤多数系统都采⽤⽤户级线程与核⼼级线程并存的⽅法。
⼀个⽤户级线程可以对应⼀个或⼏个核⼼级线程,也就是“⼀对⼀”或“多对⼀”模型。
这样既可满⾜多处理机系统的需要,也可以最⼤限度地减少调度开销。
Linux的线程实现是在核外进⾏的,核内提供的是创建进程的接⼝do_fork()。
内核提供了两个系统调⽤clone()和fork(),最终都⽤不同的参数调⽤do_fork()核内API。
当然,要想实现线程,没有核⼼对多进程(其实是轻量级进程)共享数据段的⽀持是不⾏的,因此,do_fork()提供了很多参数,包括CLONE_VM(共享内存空间)、CLONE_FS(共享⽂件系统信息)、CLONE_FILES(共享⽂件描述符表)、CLONE_SIGHAND(共享信号句柄表)和CLONE_PID(共享进程ID,仅对核内进程,即0号进程有效)。
当使⽤fork系统调⽤时,内核调⽤do_fork()不使⽤任何共享属性,进程拥有独⽴的运⾏环境,⽽使⽤pthread_create()来创建线程时,则最终设置了所有这些属性来调⽤__clone(),⽽这些参数⼜全部传给核内的do_fork(),从⽽创建的“进程”拥有共享的运⾏环境,只有栈是独⽴的,由__clone()传⼊。
Linux命令高级技巧使用xargs和parallel进行多线程命令执行

Linux命令高级技巧使用xargs和parallel进行多线程命令执行在Linux系统中,命令行操作是一项非常重要的技能,掌握高级的命令行技巧对于提高工作效率和简化复杂任务是至关重要的。
本文将介绍如何使用xargs和parallel命令进行多线程命令执行的高级技巧。
1. 使用xargs进行多线程命令执行在Linux系统中,xargs命令可以用于将标准输入的内容转化为命令行参数,并将这些参数传递给指定命令进行执行。
这使得我们可以方便地并行执行多个命令,提高执行效率。
xargs的基本语法如下:```command | xargs [options] command ...```其中,第一个command产生一系列的参数,这些参数将作为输入传递给后面的command进行执行。
下面是一个示例,展示如何使用xargs命令同时查找多个文件中包含指定关键字的行数:```find /path/to/files -name "*.txt" | xargs grep -c "keyword"```在这个例子中,find命令用于查找指定路径下的所有扩展名为.txt的文件,并将文件列表传递给xargs命令。
xargs命令再将这些文件名作为参数传递给grep命令,执行关键字查找操作。
2. 使用parallel进行多线程命令执行与xargs类似,parallel也可以用于并行执行多个命令。
不同的是,parallel可以更精确地控制线程数量和命令执行顺序。
parallel的基本语法如下:```parallel [options] command < list-of-inputs```其中,command是需要并行执行的命令,list-of-inputs是作为命令参数的输入列表。
下面的示例展示了如何使用parallel命令在多个服务器上复制文件:```parallel -S server1,server2,server3 cp source_file {} ::: destination1 destination2 destination3```在这个例子中,-S选项指定了要在哪些服务器上执行命令。
linux理发师多线程问题

用多线程同步方法解决睡眠理发师问题( Sleeping-Barber Problem)1 .操作系统:Linux2 .程序设计语言:C语言3 .设有1个理发师5把椅子(另外还有一把理发椅),几把椅子可用连续存储单元.1.技术要求:1)为每个理发师/顾客产生一个线程,设计正确的同步算法2)每个顾客进入理发室后,即时显示“Entered”及其线程自定义标识,还同时显示理发室共有几名顾客及其所坐的位置。
3)至少有10 个顾客,每人理发至少3秒钟。
4)多个顾客须共享操作函数代码。
提示:(1) 连续存储区可用数组实现。
(2) 编译命令可用:gcc -lpthread -o 目标文件名源文件名(3) 多线程编程方法参见附件。
)详细代码#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <pthread.h>#include <sys/ipc.h>#include <semaphore.h>#include <fcntl.h>#define n 5time_t end_time;sem_t mutex, customers, barbers;int count = 0;int chair [5] = {-1, -1, -1, -1, -1 };void barber(void *arg)while (time (NULL) < end_time || count>0)while (count > 0)sem_wait(&customers);sem_wait(&mutex);count--;printf ("the barber is cutting hair, count is : %d\n", count);sem_post(&mutex);sem_post(&barbers);sleep(3);void customer (void *arg)int i ,id= 0, num=0;while (time (NULL) < end_time)sem_wait(&mutex);if (count< n)count++;num= count % 5;num++;printf("customer entered:the customer %s comes in and sits at %d the chair count is:%d\n", (char *)arg, num, count);sem_post(&mutex);sem_post(&customers);sem_wait(&barbers);elsesem_post(&mutex);sleep(2);int main (int argc, char *argv[])pthread_t id1, id2, id3, id4, id5, id6, id7, id8, id9, id10, id11;int ret= 0;int i;end_time = time (NULL) + 30;sem_init (&mutex, 0, 1);ret = sem_init (&barbers, 0, 1);for (i =0;i<5;i++)chair [i] = -1;if (0!= ret)perror("sem init");ret= pthread_create (&id11, NULL, (void*)barber,"id11"); if (0!= ret)perror("create barber");ret = pthread_create ( &id1,NULL,(void*)customer, "id1"); if (0!= ret)perror("create customers");ret = pthread_create(&id2, NULL, (void*)customer, "id2"); if (0!=ret)perror("create customers");ret = pthread_create(&id3, NULL, (void*)customer, "id3"); if (0!=ret)perror("create customers");ret = pthread_create(&id4, NULL, (void*)customer, "id4"); if (0!=ret)perror("create customers");ret = pthread_create(&id5, NULL, (void*)customer, "id5"); if(0!=ret)perror("create custmers");ret = pthread_create(&id6, NULL, (void*)customer, "id6"); if (0!= ret)perror("create customers");ret = pthread_create ( &id7,NULL,(void*)customer, "id7"); if (0!= ret)perror("create customers");ret = pthread_create(&id8, NULL, (void*)customer, "id8"); if (0!=ret)perror("create customers");ret = pthread_create(&id9, NULL, (void*)customer, "id9"); if (0!=ret)perror("create customers");ret = pthread_create(&id10, NULL, (void*)customer, "id10");if (0!=ret)perror("create customers");pthread_join(id1, NULL);pthread_join(id2, NULL);pthread_join(id3, NULL);pthread_join(id4, NULL); pthread_join(id5, NULL); pthread_join(id6, NULL); pthread_join(id7, NULL); pthread_join(id8, NULL); pthread_join(id9, NULL); pthread_join(id10, NULL); pthread_join(id11, NULL); exit(0);运行结果如下。
Linux多线程编程问题

Linux 多线程编程问题1重入问题传统的UNIX没有太多考虑线程问题,库函数里过多使用了全局和静态数据,导致严重的线程重入问题。
1.1–D_REENTRANT /-pthread和errno的重入问题。
所先UNIX的系统调用被设计为出错返回-1,把错误码放在errno中(更简单而直接的方法应该是程序直接返回错误码,或者通过几个参数指针来返回)。
由于线程共享所有的数据区,而errno是一个全局的变量,这里产生了最糟糕的线程重入问题。
比如:do {bytes = recv(netfd, recvbuf, buflen, 0);} while (bytes != -1 && errno != EINTR);在上面的处理recv被信号打断的程序里。
如果这时连接被关闭,此时errno应该不等于EINTR,如果别的线程正好设置errno为EINTR,这时程序就可能进入死循环。
其它的错误码处理也可能进入不可预测的分支。
在线程需求刚开始时,很多方面技术和标准(TLS)还不够成熟,所以在为了解决这个重入问题引入了一个解决方案,把errno定义为一个宏:extern int *__errno_location (void);#define errno (*__errno_location())在上面的方案里,访问errno之前先调用__errno_location()函数,线程库提供这个函数,不同线程返回各自errno的地址,从而解决这个重入问题。
在编译时加-D_REENTRANT就是启用上面的宏,避免errno重入。
另外-D_REENTRANT还影响一些stdio的函数。
在较高版本的gcc里,有很多嵌入函数的优化,比如把printf(“Hello\n”);优化为puts(“hello\n”);之类的,有些优化在多线程下有问题。
所以gcc引入了–pthread 参数,这个参数出了-D_REENTRANT外,还校正一些针对多线程的优化。
linux多线程全面解析

linux多线程全⾯解析引⼊:在传统的Unix模型中,当⼀个进程需要由另⼀个实体执⾏某件事时,该进程派⽣(fork)⼀个⼦进程,让⼦进程去进⾏处理。
Unix下的⼤多数⽹络服务器程序都是这么编写的,即⽗进程接受连接,派⽣⼦进程,⼦进程处理与客户的交互。
虽然这种模型很多年来使⽤得很好,但是fork时有⼀些问题:fork是昂贵的。
内存映像要从⽗进程拷贝到⼦进程,所有描述字要在⼦进程中复制等等。
⽬前有的Unix实现使⽤⼀种叫做写时拷贝(copy-on-write)的技术,可避免⽗进程数据空间向⼦进程的拷贝。
尽管有这种优化技术,fork仍然是昂贵的。
2. fork⼦进程后,需要⽤进程间通信(IPC)在⽗⼦进程之间传递信息。
Fork之前的信息容易传递,因为⼦进程从⼀开始就有⽗进程数据空间及所有描述字的拷贝。
但是从⼦进程返回信息给⽗进程需要做更多的⼯作。
线程有助于解决这两个问题。
线程有时被称为轻权进程(lightweight process),因为线程⽐进程“轻权”,⼀般来说,创建⼀个线程要⽐创建⼀个进程快10~100倍。
⼀个进程中的所有线程共享相同的全局内存,这使得线程很容易共享信息,但是这种简易性也带来了同步问题。
⼀个进程中的所有线程不仅共享全局变量,⽽且共享:进程指令、⼤多数数据、打开的⽂件(如描述字)、信号处理程序和信号处置、当前⼯作⽬录、⽤户ID和组ID。
但是每个线程有⾃⼰的线程ID、寄存器集合(包括程序计数器和栈指针)、栈(⽤于存放局部变量和返回地址)、error、信号掩码、优先级。
在Linux中线程编程符合Posix.1标准,称为Pthreads。
所有的pthread函数都以pthread_开头。
在调⽤它们前均要包括pthread.h头⽂件,⼀个函数库libpthread实现。
1.线程基础介绍:数据结构:pthread_t:线程的IDpthread_attr_t:线程的属性操作函数:pthread_create():创建⼀个线程pthread_exit():终⽌当前线程pthread_cancel():中断另外⼀个线程的运⾏pthread_join():阻塞当前的线程,直到另外⼀个线程运⾏结束pthread_attr_init():初始化线程的属性pthread_attr_setdetachstate():设置脱离状态的属性(决定这个线程在终⽌时是否可以被结合)pthread_attr_getdetachstate():获取脱离状态的属性pthread_attr_destroy():删除线程的属性pthread_kill():向线程发送⼀个信号同步函数:⽤于 mutex 和条件变量pthread_mutex_init()初始化互斥锁pthread_mutex_destroy()删除互斥锁pthread_mutex_lock():占有互斥锁(阻塞操作)pthread_mutex_trylock():试图占有互斥锁(不阻塞操作)。
linux环境多线程出错处理的分析

一、可行性分析 (1)(一)、信号及信号来源 (1)(二)信号的种类 (4)(三)试验 (11)一、可行性分析信号是通知进程已发生某种条件的一种技术。
例如,若某一进程执行除法操作,其除数为0,则将名为SIGFPE的信号发送给该进程。
进程如何处理信号有三种选择:* 忽视该信号。
有些信号表示异常发生,例如,除以0或访问进程地址空间以外的单元等,因为这些异常产生的后果不确定,所以不推荐使用这种处理方式。
* 按系统默认方式处理。
对于0除,系统默认方式是终止该进程。
* 提供一个函数,信号发生时则可以调用该函数。
使用这种方式,我们将能够知道什么时候产生了信号,并按所希望的方式处理它。
由此可见,利用信号机制,可以实现对一些异常信息的监控处理;为了更好的理解,有必要先对信号的原理,以及处理机制进行描述:(一)、信号及信号来源信号本质信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。
信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。
信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。
信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息。
信号来源信号事件的发生有两个来源:硬件来源(比如我们按下了键盘或者其它硬件故障);软件来源,最常用发送信号的系统函数是kill, raise, alarm和setitimer以及sigqueue函数,软件来源还包括一些非法运算等操作。
注:就我们目前的应用目的来说,我们的重点应该是软件来源的信号.现在分析一下软件来源的几个信号发送系统函数:1、kill()#include <sys/types.h>#include <signal.h>int kill(pid_t pid,int signo)参数pid的值信号的接收进程/线程pid>0 进程ID为pid的进程/线程pid=0 同一个进程组的进程pid<0 && pid!=-1 进程组ID为-pid的所有进程pid=-1 除发送进程自身外,所有进程ID大于1的进程Signo是信号值,当为0时(即空信号),实际不发送任何信号,但照常进行错误检查,因此,可用于检查目标进程是否存在,以及当前进程是否具有向目标发送信号的权限(root 权限的进程可以向任何进程发送信号,非root权限的进程只能向属于同一个session或者同一个用户的进程发送信号)。
linux 多线程 面试题

linux 多线程面试题Linux多线程面试题一、进程与线程的基本概念及区别进程是指在操作系统中运行的一个程序的实例。
每个进程都有自己的独立地址空间,包括代码、数据和堆栈等。
进程间通信可以通过共享内存、管道、信号等方式实现。
线程是进程中的一个执行单元,一个进程中可以拥有多个线程,它们共享相同的地址空间。
线程之间可以并发执行,共享进程的资源,如全局变量、堆内存等。
区别:1. 资源占用:进程拥有独立的地址空间,占用的资源较多;而线程共享相同的地址空间,仅需较少的资源。
2. 创建与销毁:创建和销毁进程的开销较大;线程的创建和销毁开销较小。
3. 并发性与共享性:多个进程之间的执行是并发的,进程间通信的开销较大;多个线程之间的执行是并发的,线程间通信的开销较小。
二、常见的线程同步机制1. 互斥锁:互斥锁用于保护共享资源,同一时间只允许一个线程访问。
当一个线程获得了互斥锁后,其他线程需要等待直到该线程释放锁。
2. 读写锁:读写锁分为读锁和写锁。
读锁可以被多个线程同时持有,用于保护读操作;写锁只能被一个线程持有,用于保护写操作。
3. 条件变量:条件变量用于线程之间的等待和通知。
一个线程可以在满足某个条件之前等待,而另一个线程满足条件后可以通过通知唤醒等待的线程。
4. 信号量:信号量用于控制同一时刻可以访问共享资源的线程数量。
当信号量值大于0时,线程可以访问资源;当信号量值为0时,线程需要等待。
三、线程死锁的原因及预防方法线程死锁是指两个或多个线程互相持有对方需要的资源,导致彼此无法继续执行的情况。
常见的造成死锁的原因:1. 互斥使用:多个线程竞争同一资源,且每个线程只能独占资源。
2. 资源的不可剥夺性:已经获得的资源无法被其他线程抢占。
3. 循环等待:若干线程之间形成一种头尾相接的循环等待资源的关系。
预防死锁的方法:1. 避免使用多个锁:尽量使用同一个锁来保护多个资源。
2. 避免嵌套锁:如果一个线程持有一个锁A的同时又想获得另一个锁B,但另一个线程正好相反,容易造成死锁。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
用多线程同步方法解决睡眠理发师问题(Sleeping-Barber Problem)
1 .操作系统: Linux
2 .程序设计语言:C语言
3 .设有1个理发师5把椅子(另外还有一把理发椅),几把椅子可用连续存储单元.
1.技术要求:
1)为每个理发师/顾客产生一个线程,设计正确的同步算法
2)每个顾客进入理发室后,即时显示“Entered”及其线程自定义标识,还同时显示理发室共有几名顾客及其所坐的位置。
3)至少有10 个顾客,每人理发至少3秒钟。
4)多个顾客须共享操作函数代码。
提示:
(1) 连续存储区可用数组实现。
(2) 编译命令可用:gcc -lpthread -o 目标文件名源文件名
(3) 多线程编程方法参见附件。
)
详细代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/ipc.h>
#include <semaphore.h>
#include <fcntl.h>
#define n 5
time_t end_time;
sem_t mutex, customers, barbers;
int count = 0;
int chair [5] = {-1, -1, -1, -1, -1 };
void barber(void *arg)
{
while (time (NULL) < end_time || count>0)
while (count > 0)
{
sem_wait(&customers);
sem_wait(&mutex);
count--;
printf ("the barber is cutting hair, count is : %d\n", count);
sem_post(&mutex);
sem_post(&barbers);
sleep(3);
}
}
void customer (void *arg)
{
int i ,id= 0, num=0;
while (time (NULL) < end_time)
{
sem_wait(&mutex);
if (count< n)
{
count++;
num= count % 5;
num++;
printf("customer entered:the customer %s comes in and sits at %d the chair count is: %d\n", (char *)arg, num, count);
sem_post(&mutex);
sem_post(&customers);
sem_wait(&barbers);
}
else
{
sem_post(&mutex);
}
sleep(2);
}
}
int main (int argc, char *argv[])
{
pthread_t id1, id2, id3, id4, id5, id6, id7, id8, id9, id10, id11; int ret= 0;
int i;
end_time = time (NULL) + 30;
sem_init (&mutex, 0, 1);
ret = sem_init (&barbers, 0, 1);
for (i =0;i<5;i++)
{
chair [i] = -1;
}
if (0!= ret)
perror("sem init");
ret= pthread_create (&id11, NULL, (void*)barber,"id11"); if (0!= ret)
perror("create barber");
ret = pthread_create ( &id1,NULL,(void*)customer, "id1"); if (0!= ret)
perror("create customers");
ret = pthread_create(&id2, NULL, (void*)customer, "id2"); if (0!=ret)
perror("create customers");
ret = pthread_create(&id3, NULL, (void*)customer, "id3"); if (0!=ret)
perror("create customers");
ret = pthread_create(&id4, NULL, (void*)customer, "id4"); if (0!=ret)
perror("create customers");
ret = pthread_create(&id5, NULL, (void*)customer, "id5");
if(0!=ret)
perror("create custmers");
ret = pthread_create(&id6, NULL, (void*)customer, "id6"); if (0!= ret)
perror("create customers");
ret = pthread_create ( &id7,NULL,(void*)customer, "id7"); if (0!= ret)
perror("create customers");
ret = pthread_create(&id8, NULL, (void*)customer, "id8"); if (0!=ret)
perror("create customers");
ret = pthread_create(&id9, NULL, (void*)customer, "id9"); if (0!=ret)
perror("create customers");
ret = pthread_create(&id10, NULL, (void*)customer, "id10"); if (0!=ret)
perror("create customers");
pthread_join(id1, NULL);
pthread_join(id2, NULL);
pthread_join(id3, NULL);
pthread_join(id4, NULL);
pthread_join(id5, NULL);
pthread_join(id6, NULL);
pthread_join(id7, NULL);
pthread_join(id8, NULL); pthread_join(id9, NULL);
pthread_join(id10, NULL);
pthread_join(id11, NULL); exit(0);
}
运行结果如下。