📄 00000003.htm
字号:
<HTML><HEAD> <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人: reden (Offer 快快来啊 ~!), 信区: Linux <BR>标 题: Linux程式设计入门 - fork, pthread, and signals <BR>发信站: BBS 水木清华站 (Thu Apr 1 19:57:47 1999) <BR> <BR>Linux程式设计入门 - fork, pthread, and signals <BR> <BR> <BR> <BR> 在UNIX程式设计中,学会fork及signal的运用,算是相当基本的功夫。 <BR> <BR> <BR> fork()及signal经常运用在daemon守护神这一类常驻程式,另外像 <BR> <BR> a4c.tty/yact/chdrv这些中文终端机程式也有用到,一般如 <BR> <BR> Mozilla/Apache/Squid等大程式几乎都一定会用到。 <BR> <BR> <BR> 虽然在UNIX下的程式写作,对thread的功能需求并非很大,但thread在现代的 <BR> <BR> 作业系统中,几乎都已经存在了。pthread是Linux上的thread函数库,如果您 <BR> <BR> 要在Linux下撰写多线程式,例如MP3播放程式,熟悉pthread的用法是必要的。 <BR> <BR> <BR> pthread及signal都可以用一大章来讨论。在这里,我只谈及最简单及常用的技 <BR> <BR> 巧,当您熟悉这些基本技巧的运用後,再找一些专门深入探讨pthread及signal <BR> <BR> 程式写作的书籍来研究。这些进阶的写法,用到的机会较少,将层次分明,学 <BR> <BR> 习速度应该会比较快。 <BR> <BR> <BR> <BR> 程序分歧fork() <BR> <BR> <BR> fork()会产生一个与父程序相同的子程序,唯一不同之处在於其process <BR> <BR> id(pid)。 <BR> <BR> <BR> 如果我们要撰写守护神程式,或是例如网路伺服器,需要多个行程来同时提供 <BR> <BR> 多个连线,可以利用fork()来产生多个相同的行程。 <BR> <BR> <BR> 函数宣告 <BR> <BR> <BR> pid_t fork(void); <BR> <BR> pid_t vfork(void); <BR> <BR> <BR> 返回值: <BR> <BR> <BR> -1 : 失败。 <BR> <BR> 0 : 子程序。 <BR> <BR> >0 : 将子程序的process id传回给父程序。 <BR> <BR> <BR> 在Linux下fork()及vfork()是相同的东西。 <BR> <BR> <BR> 范例一: fork.c <BR> <BR> <BR> 在这个范例中,我们示范fork()的标准用法。 <BR> <BR> <BR> #include <stdio.h> <BR> <BR> #include <stdlib.h> <BR> <BR> #include <unistd.h> <BR> <BR> <BR> void main(void) <BR> <BR> { <BR> <BR> pid_t pid; <BR> <BR> <BR> printf("hello\n"); <BR> <BR> pid = fork(); <BR> <BR> <BR> switch (pid) { <BR> <BR> case -1: printf("failure!\n"); break; <BR> <BR> case 0: printf("I am child!\n"); break; <BR> <BR> default: printf("my child is %d\n",pid); break; <BR> <BR> } <BR> <BR> for (;;) { /* do something here */ } <BR> <BR> } <BR> <BR> <BR> 编译: <BR> <BR> <BR> gcc -o ex1 fork.c <BR> <BR> <BR> 执行结果: <BR> <BR> <BR> ./ex1 & <BR> <BR> <BR> hello <BR> <BR> my child is 8650 <BR> <BR> I am child! <BR> <BR> <BR> 我们可以见到,使用fork(),可将一个程式分岐成两个。在分歧之前的程式码 <BR> <BR> 只执行一次。 <BR> <BR> <BR> 检验行程: <BR> <BR> <BR> ps | grep ex1 <BR> <BR> <BR> 8649 p0 R 0:40 ./ex1 <BR> <BR> 8650 p0 R 0:40 ./ex1 <BR> <BR> <BR> 8649是父程序的pid,8650则为子程序的pid。 <BR> <BR> 您会需要用到"killall ex1"来杀掉两个行程。 <BR> <BR> <BR> 范例二: daemon.c <BR> <BR> <BR> 在UNIX中,我们一般都利用fork(),来实作所谓的"守护神程式",也就是DOS中 <BR> <BR> 所谓的"常驻程式"。一般的技巧是将父程序结束,而子程序便成为"守护神"。 <BR> <BR> <BR> 这个范例中,示范一般标准的daemon写法。 <BR> <BR> <BR> #include <stdio.h> <BR> <BR> #include <stdlib.h> <BR> <BR> #include <unistd.h> <BR> <BR> <BR> void main(void) <BR> <BR> { <BR> <BR> pid_t pid; <BR> <BR> <BR> pid = fork(); <BR> <BR> <BR> if (pid>0) { <BR> <BR> printf("daemon on duty!\n"); <BR> <BR> exit(0); <BR> <BR> } else <BR> <BR> if (pid<0) { <BR> <BR> printf("Can't fork!\n"); <BR> <BR> exit(-1); <BR> <BR> } <BR> <BR> <BR> for (;;) { <BR> <BR> printf("I am the daemon!\n"); <BR> <BR> sleep(3); <BR> <BR> /* do something your own here */ <BR> <BR> } <BR> <BR> <BR> } <BR> <BR> <BR> 编译: <BR> <BR> <BR> gcc -o ex2 daemon.c <BR> <BR> <BR> 执行结果: <BR> <BR> <BR> ./ex2 <BR> <BR> <BR> daemon on duty! <BR> <BR> I am the daemon! <BR> <BR> 接下来每三秒钟,都会出现一个"I am the daemon!"的讯息,这表示您的程式 <BR> <BR> 已经"长驻"在系统中了。 <BR> <BR> <BR> 检验行程: <BR> <BR> <BR> ps | grep ex2 <BR> <BR> <BR> 8753 p0 S 0:00 ./ex2 <BR> <BR> <BR> 注意到在范例一中,我们下的指令为"./ex1 &",而在范例二中为"./ex2",没 <BR> <BR> 有"&"符号。 <BR> <BR> <BR> <BR> <BR> 范例三: lock.c <BR> <BR> <BR> 许多的时候,我们希望"守护神"在系统中只有一个,这时候会需要用到pid <BR> <BR> lock的技巧。如果您注意到/var/run目录中的内容,您会发现到有许多的*.pid <BR> <BR> 档,观看其内容都是一些数字,这些数字其实就是该行程的pid。 <BR> <BR> <BR> #include <stdio.h> <BR> <BR> #include <stdlib.h> <BR> <BR> #include <unistd.h> <BR> <BR> <BR> void main(void) <BR> <BR> { <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -