Linux信号与线程,Linux常见面试题

大家好,今天来为大家解答Linux信号与线程这个问题的一些问题点,包括Linux常见面试题也一样很多人还不知道,因此呢,今天就来为大家分析分析,现在让我们一起来看看吧!如果解决了您的问题,还望您关注下本站哦,谢谢~

linux多线程信号量sem_wait()到sem_post()之间逻辑代码是

在处理Linux多线程中的信号量操作,如`sem_wait()`与`sem_post()`之间的逻辑代码,确保共享变量的安全访问,确实需要增加互斥锁。此操作在生产者线程与消费者线程数量大于2个时显得尤为重要。以下分析生产者与消费者函数中的关键问题与解决策略。

在生产者函数中,不同线程可能会相互覆盖数据,导致数据错乱或相同。这种混乱可能源于多个线程同时访问并修改同一共享资源,引发数据竞争问题。为避免这种情况,我们需确保在`sem_wait()`调用前获取互斥锁。当`sem_wait()`调用成功后,生产者可以安全地申请新空间,而不必担心被其他线程干扰。同样,当生产者完成空间申请后,通过`sem_post()`释放信号量,这时也应在释放互斥锁之后执行,以确保其他线程能正确响应信号量的变化。

消费者函数中,链表删除操作可能出现问题,或重复释放已删除的节点,这也与共享资源的访问控制不当有关。消费者线程在从链表中删除节点时,应确保在执行删除操作前锁定互斥锁,以防止其他线程在删除操作进行时访问或修改该节点。同时,当消费者释放资源时,同样需要在释放互斥锁后进行,确保资源释放的正确性和线程间的协调。

为了确保资源的正确管理,将生产者申请空间的操作放到`while`循环的开头并将其移出,意味着在每次循环开始时都检查信号量状态,避免了不必要的重复操作。同时,将释放空间的部分移出`while`循环,意味着当`while`循环退出时才进行资源释放,从而确保在正确的时间点释放资源。

综上所述,增加互斥锁作为`sem_wait()`与`sem_post()`之间的关键控制点,能够有效防止多线程环境中由于数据竞争导致的错误,确保了线程间的协同工作以及资源的正确管理。正确处理这些细节,能够显著提升系统的稳定性和效率。

Linux中,shell脚本如何使用信号机制去控制线程的开启关闭

trap是Linux的内建命令,用于捕捉信号,trap命令可以指定收到某种信号时所执行的命令。trap命令的格式如下:trap command sig1 sig2... sigN,当接收到sinN中任意一个信号时,执行command命令,command命令完成后继续接收到信号前的操作,直到脚本结束。利用trap命令捕捉INT信号(即与Ctrl+c绑定的中断信号)。trap还可以忽略某些信号,将command用空字符串代替即可,如trap"" TERM INT,忽略kill%n和Ctrl+c发送的信号(kill发送的是TERM信号)。Linux更强劲的杀死进程的命令:kill-9进程号(或kill-9%n作业号)等价与kill-KILL进程号。

举个例子:

最近小A需要生产2015年全年的KPI数据报表,现在小A已经将生产脚本写好了,生产脚本一次只能生产指定一天的KPI数据,假设跑一次生产脚本需要5分钟,那么:

如果是循环顺序执行,那么需要时间:5* 365= 1825分钟,约等于 6天

如果是一次性放到linux后台并发执行,365个后台任务,系统可承受不住哦!

既然不能一次性把365个任务放到linux后台执行,那么,能不能实现自动地每次将N个任务放到后台并发执行呢?当然是可以的啦。

#!/bin/bash

source/etc/profile;

#-----------------------------

tempfifo=$$.fifo#$$表示当前执行文件的PID

begin_date=$1#开始时间

end_date=$2#结束时间

if[$#-eq2]

then

if["$begin_date"\>"$end_date"]

then

echo"Error!$begin_dateisgreaterthan$end_date"

exit1;

fi

else

echo"Error!Notenoughparams."

echo"Sample:shloop_kpi2015-12-012015-12-07"

exit2;

fi

#-----------------------------

trap"exec1000>&-;exec1000<&-;exit0"2

mkfifo$tempfifo

exec1000<>$tempfifo

rm-rf$tempfifo

for((i=1;i<=8;i++))

do

echo>&1000

done

while[$begin_date!=$end_date]

do

read-u1000

{

echo$begin_date

hive-fkpi_report.sql--hivevardate=$begin_date

echo>&1000

}&

begin_date=`date-d"+1day$begin_date"+"%Y-%m-%d"`

done

wait

echo"done!!!!!!!!!!"

第6~22行:比如:sh loop_kpi_report.sh 2015-01-01 2015-12-01:

$1表示脚本入参的第一个参数,等于2015-01-01

$2表示脚本入参的第二个参数,等于2015-12-01

$#表示脚本入参的个数,等于2

第13行用于比较传入的两个日期的大小,\>是转义

第26行:表示在脚本运行过程中,如果接收到Ctrl+C中断命令,则关闭文件描述符1000的读写,并正常退出

exec 1000>&-;表示关闭文件描述符1000的写

exec 1000<&-;表示关闭文件描述符1000的读

trap是捕获中断命令

第27~29行:

第27行,创建一个管道文件

第28行,将文件描述符1000与FIFO进行绑定,<读的绑定,>写的绑定,<>则标识对文件描述符1000的所有操作等同于对管道文件$tempfifo的操作

第29行,可能会有这样的疑问:为什么不直接使用管道文件呢?事实上这并非多此一举,管道的一个重要特性,就是读写必须同时存在,缺失某一个操作,另一个操作就是滞留,而第28行的绑定文件描述符(读、写绑定)正好解决了这个问题

第31~34行:对文件描述符1000进行写入操作。通过循环写入8个空行,这个8就是我们要定义的后台并发的线程数。为什么是写空行而不是写其它字符?因为管道文件的读取,是以行为单位的

第37~42行:

第37行,read-u1000的作用就是读取管道中的一行,在这里就是读取一个空行;每次读取管道就会减少一个空行

第39~41行,注意到第42行结尾的&吗?它表示进程放到linux后台中执行

第41行,执行完后台任务之后,往文件描述符1000中写入一个空行。这是关键所在了,由于read-u1000每次操作,都会导致管道减少一个空行,当linux后台放入了8个任务之后,由于文件描述符1000没有可读取的空行,将导致read-u1000一直处于等待。

c语言实例,linux线程同步的信号量方式 谢谢

这么高的悬赏,实例放后面。信号量(sem),如同进程一样,线程也可以通过信号量来实现通信,虽然是轻量级的。信号量函数的名字都以"sem_"打头。线程使用的基本信号量函数有四个。

信号量初始化。

intsem_init(sem_t*sem,intpshared,unsignedintvalue);

这是对由sem指定的信号量进行初始化,设置好它的共享选项(linux只支持为0,即表示它是当前进程的局部信号量),然后给它一个初始值VALUE。

等待信号量。给信号量减1,然后等待直到信号量的值大于0。

intsem_wait(sem_t*sem);

释放信号量。信号量值加1。并通知其他等待线程。

intsem_post(sem_t*sem);

销毁信号量。我们用完信号量后都它进行清理。归还占有的一切资源。

intsem_destroy(sem_t*sem);

#include<stdlib.h>

#include<stdio.h>

#include<unistd.h>

#include<pthread.h>

#include<semaphore.h>

#include<errno.h>

#definereturn_if_fail(p)if((p)==0){printf("[%s]:funcerror!/n",__func__);return;}

typedefstruct_PrivInfo

{

sem_ts1;

sem_ts2;

time_tend_time;

}PrivInfo;

staticvoidinfo_init(PrivInfo*thiz);

staticvoidinfo_destroy(PrivInfo*thiz);

staticvoid*pthread_func_1(PrivInfo*thiz);

staticvoid*pthread_func_2(PrivInfo*thiz);

intmain(intargc,char**argv)

{

pthread_tpt_1=0;

pthread_tpt_2=0;

intret=0;

PrivInfo*thiz=NULL;

thiz=(PrivInfo*)malloc(sizeof(PrivInfo));

if(thiz==NULL)

{

printf("[%s]:Failedtomallocpriv./n");

return-1;

}

info_init(thiz);

ret=pthread_create(&pt_1,NULL,(void*)pthread_func_1,thiz);

if(ret!=0)

{

perror("pthread_1_create:");

}

ret=pthread_create(&pt_2,NULL,(void*)pthread_func_2,thiz);

if(ret!=0)

{

perror("pthread_2_create:");

}

pthread_join(pt_1,NULL);

pthread_join(pt_2,NULL);

info_destroy(thiz);

return0;

}

staticvoidinfo_init(PrivInfo*thiz)

{

return_if_fail(thiz!=NULL);

thiz->end_time=time(NULL)+10;

sem_init(&thiz->s1,0,1);

sem_init(&thiz->s2,0,0);

return;

}

staticvoidinfo_destroy(PrivInfo*thiz)

{

return_if_fail(thiz!=NULL);

sem_destroy(&thiz->s1);

sem_destroy(&thiz->s2);

free(thiz);

thiz=NULL;

return;

}

staticvoid*pthread_func_1(PrivInfo*thiz)

{

return_if_fail(thiz!=NULL);

while(time(NULL)<thiz->end_time)

{

sem_wait(&thiz->s2);

printf("pthread1:pthread1getthelock./n");

sem_post(&thiz->s1);

printf("pthread1:pthread1unlock/n");

sleep(1);

}

return;

}

staticvoid*pthread_func_2(PrivInfo*thiz)

{

return_if_fail(thiz!=NULL);

while(time(NULL)<thiz->end_time)

{

sem_wait(&thiz->s1);

printf("pthread2:pthread2gettheunlock./n");

sem_post(&thiz->s2);

printf("pthread2:pthread2unlock./n");

sleep(1);

}

return;

}

阅读剩余
THE END