分享
 
 
 

Linux程式设计入门 fork/pthread/signals

王朝system·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

fork()及signal经常运用在daemon守护神这一类常驻程式,另外像a4c.tty/yact/chdrv这些中文终端机程式也有用到,一般如Mozilla/Apache/Squid等大程式几乎都一定会用到。

虽然在UNIX下的程式写作,对thread的功能需求并非很大,但thread在现代的作业系统中,几乎都已经存在了。pthread是Linux上的thread函数库,如果您要在Linux下撰写多线程式,例如MP3播放程式,熟悉pthread的用法是必要的。

pthread及signal都可以用一大章来讨论。在这里,我只谈及最简单及常用的技巧,当您熟悉这些基本技巧的运用後,再找一些专门深入探讨pthread及signal程式写作的书籍来研究。这些进阶的写法,用到的机会较少,将层次分明,学习速度应该会比较快。

程序分歧fork()

fork()会产生一个与父程序相同的子程序,唯一不同之处在於其processid(pid)。

如果我们要撰写守护神程式,或是例如网路伺服器,需要多个行程来同时提供多个连线,可以利用fork()来产生多个相同的行程。

函数宣告

pid_tfork(void);

pid_tvfork(void);

返回值:

-1:失败。

0:子程序。

>0:将子程序的processid传回给父程序。

在Linux下fork()及vfork()是相同的东西。

范例一:fork.c

在这个范例中,我们示范fork()的标准用法。

#include

#include

#include

voidmain(void)

{

pid_tpid;

printf("hello\n");

pid=fork();

switch(pid){

case-1:printf("failure!\n");break;

case0:printf("Iamchild!\n");break;

default:printf("mychildis%d\n",pid);break;

}

for(;;){/*dosomethinghere*/}

}

编译:

gcc-oex1fork.c

执行结果:

./ex1&

hello

mychildis8650

Iamchild!

我们可以见到,使用fork(),可将一个程式分岐成两个。在分歧之前的程式码只执行一次。

检验行程:

ps|grepex1

8649p0R0:40./ex1

8650p0R0:40./ex1

8649是父程序的pid,8650则为子程序的pid。

您会需要用到"killallex1"来杀掉两个行程。

范例二:daemon.c

在UNIX中,我们一般都利用fork(),来实作所谓的"守护神程式",也就是DOS中所谓的"常驻程式"。一般的技巧是将父程序结束,而子程序便成为"守护神"。

这个范例中,示范一般标准的daemon写法。

#include

#include

#include

voidmain(void)

{

pid_tpid;

pid=fork();

if(pid>0){

printf("daemononduty!\n");

exit(0);

}else

if(pid<0){

printf("Can'tfork!\n");

exit(-1);

}

for(;;){

printf("Iamthedaemon!\n");

sleep(3);

/*dosomethingyourownhere*/

}

}

编译:

gcc-oex2daemon.c

执行结果:

./ex2

daemononduty!

Iamthedaemon!

接下来每三秒钟,都会出现一个"Iamthedaemon!"的讯息,这表示您的程式已经"长驻"在系统中了。

检验行程:

ps|grepex2

8753p0S0:00./ex2

注意到在范例一中,我们下的指令为"./ex1&",而在范例二中为"./ex2",没有"&"符号。

范例三:lock.c

许多的时候,我们希望"守护神"在系统中只有一个,这时候会需要用到pidlock的技巧。如果您注意到/var/run目录中的内容,您会发现到有许多的*.pid档,观看其内容都是一些数字,这些数字其实就是该行程的pid。

#include

#include

#include

voidmain(void)

{

FILE*fp;

pid_tpid;

exit(-1);

}

act.sa_handler=quit;

act.sa_flags=0;

sigemptyset(&act.sa_mask);

sigaction(SIGTERM,&act,NULL);

sigaction(SIGHUP,&act,NULL);

sigaction(SIGINT,&act,NULL);

sigaction(SIGQUIT,&act,NULL);

sigaction(SIGUSR1,&act,NULL);

sigaction(SIGUSR2,&act,NULL);

for(;;){

sleep(3);

}

}

编译:

gcc-oex1lock.c

执行

./ex1

daemononduty!

送信号

我们先找出该守护神程式的pid

PID=`cat/var/run/lock.pid`

接下来利用kill来送信号

kill$PID

Receivesignal15

程式将会结束,并且/var/run/lock.pid将会被删除掉,以便下一次daemon再启动。注意到如果quit函数内,没有放exit(),程式将永远杀不掉。

接下来送一些其它的信号试试看。

./ex1

PID=`cat/var/run/lock.pid`

kill-HUP$PID

Receivesignal1

您可以自行试试

kill-INT$PID

kill-QUIT$PID

kill-ILL$PID

.

.

.

等等这些信号,看看他们的结果如何。

信号的定义

在/usr/include/signum.h中有各种信号的定义

#defineSIGHUP1/*Hangup(POSIX).*/

#defineSIGINT2/*Interrupt(ANSI).*/

#defineSIGQUIT3/*Quit(POSIX).*/

#defineSIGILL4/*Illegalinstruction(ANSI).*/

#defineSIGTRAP5/*Tracetrap(POSIX).*/

#defineSIGABRT6/*Abort(ANSI).*/

#defineSIGIOT6/*IOTtrap(4.2BSD).*/

#defineSIGBUS7/*BUSerror(4.2BSD).*/

#defineSIGFPE8/*Floating-pointexception(ANSI).

*/

#defineSIGKILL9/*Kill,unblockable(POSIX).*/

#defineSIGUSR110/*User-definedsignal1(POSIX).*/

#defineSIGSEGV11/*Segmentationviolation(ANSI).*/

#defineSIGUSR212/*User-definedsignal2(POSIX).*/

#defineSIGPIPE13/*Brokenpipe(POSIX).*/

#defineSIGALRM14/*Alarmclock(POSIX).*/

#defineSIGTERM15/*Termination(ANSI).*/

#defineSIGSTKFLT16/*???*/

#defineSIGCLDSIGCHLD/*SameasSIGCHLD(SystemV).*/

#defineSIGCHLD17/*Childstatushaschanged(POSIX).

*/

#defineSIGCONT18/*Continue(POSIX).*/

#defineSIGSTOP19/*Stop,unblockable(POSIX).*/

#defineSIGTSTP20/*Keyboardstop(POSIX).*/

#defineSIGTTIN21/*Backgroundreadfromtty(POSIX).

*/

#defineSIGTTOU22/*Backgroundwritetotty(POSIX).

*/

#defineSIGURG23/*Urgentconditiononsocket(4.2

BSD).*/

#defineSIGXCPU24/*CPUlimitexceeded(4.2BSD).*/

#defineSIGXFSZ25/*Filesizelimitexceeded(4.2

BSD).*/

#defineSIGVTALRM26/*Virtualalarmclock(4.2BSD).*/

#defineSIGPROF27/*Profilingalarmclock(4.2BSD).

*/

#defineSIGWINCH28/*Windowsizechange(4.3BSD,Sun).

*/

#defineSIGPOLLSIGIO/*Pollableeventoccurred(System

V).*/

#defineSIGIO29/*I/Onowpossible(4.2BSD).*/

#defineSIGPWR30/*Powerfailurerestart(SystemV).

*/

#defineSIGUNUSED31

函数宣告:

SignalOperators

intsigemptyset(sigset_t*set);

intsigfillset(sigset_t*set);

intsigaddset(sigset_t*set,intsignum);

intsigdelset(sigset_t*set,intsignum);

intsigismember(constsigset_t*set,intsignum);

SignalHandlingFunctions

intsigaction(intsignum,conststructsigaction*act,struct

sigaction*oldact);

intsigprocmask(inthow,constsigset_t*set,sigset_t

*oldset);

intsigpending(sigset_t*set);

intsigsuspend(constsigset_t*mask);

StructureSignalAction

structsigaction{

void(*sa_handler)(int);

sigset_tsa_mask;

intsa_flags;

void(*sa_restorer)(void);

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有