Unix程序设计基础第三讲.ppt

上传人:牧羊曲112 文档编号:6522542 上传时间:2023-11-08 格式:PPT 页数:34 大小:210.49KB
返回 下载 相关 举报
Unix程序设计基础第三讲.ppt_第1页
第1页 / 共34页
Unix程序设计基础第三讲.ppt_第2页
第2页 / 共34页
Unix程序设计基础第三讲.ppt_第3页
第3页 / 共34页
Unix程序设计基础第三讲.ppt_第4页
第4页 / 共34页
Unix程序设计基础第三讲.ppt_第5页
第5页 / 共34页
点击查看更多>>
资源描述

《Unix程序设计基础第三讲.ppt》由会员分享,可在线阅读,更多相关《Unix程序设计基础第三讲.ppt(34页珍藏版)》请在三一办公上搜索。

1、Unix程序设计基础 第三讲,谢翰2004-2-10,Reviews of last class,进程独立地址空间的指令序列五种状态基本状态:新建,就绪,运行,睡眠,僵死状态转换图进程ID,子进程,父进程Unix下的多进程编程fork与execve:进程的创建与程序的运行wait,waitpid:回收子进程的退出状态,Reviews of last class,信号是Unix操作系统用来通知进程发生了某种事件的一种手段。也称为软件中断几个常用的信号信号编程signal与sigaction:改变信号动作alarm:设置闹钟不可重入函数:在函数返回之前不可再次被调用,如printf,malloc。

2、,信号编程(续),功能更强的改变信号动作函数:sigaction。解决早期signal函数的不可靠问题:在信号处理过程中再次收到这个信号怎么办?一般情况下用不到,请自己看书。发送信号函数kill与raise。函数原型:#include int kill(pid_t pid,int sig);int raise(int sig);,信号的发送,kill给进程号为pid的进程发送一个sig信号pid 0:发送给进程ID为pid的进程pid=0:发送给与自己同组,并且自己有权限向其发送的进程pid-1:发送给进程组ID为-pid的进程,并且自己有权限向其发送的进程pid=-1:所有自己有权限向其发送

3、信号的进程,信号的发送,raise调用给自己发关一个sig信号。因此,raise(sig);等价于kill(getpid(),sig);发送信号的shell命令:kill。在默认情况下发送的是SIGTERM信号$kill 12345 等价于$kill TERM 12345,都是向进程12345发送一个SIGTERM信号。$kill KILL 12345,向进程12345发送一个SIGKILL信号,信号的屏蔽,在一段时间内屏蔽掉某些信号,让当前进程接收不到这些信号。与忽略信号(remember?)不同,被屏蔽的信号会被保存起来(但不排队),在屏蔽解除后会被进程收到。注意一点:一般情况下用sign

4、al函数设置信号动作,在某信号处理过程中,该信号是被屏蔽的。,实例:SIGCHLD信号,不详细讲关于信号屏蔽的系统调用,因为不是很重要,而且内容太多。但我想通过一个例子来让大家了解信号屏蔽:某个进程通过调用fork创建多个子进程:for(i=0;i n;i+)if(pid=fork()=0)break;,实例:SIGCHLD信号,当父进程给束之前,必须调用wait来回收子进程的退出状态,如:for(i=0;i n;i+)wait(但这就存在一个问题:只有当父进程结束子进程的状态才能被回收,子进程占用的进程表项才可以被释放。能不能子进程一结束就把它回收?,实例:SIGCHLD信号,回顾上一结,有

5、一个信号叫做SIGCHLD,当子进程停止或结束,父进程将收到一个SIGCHLD信号,默认动作是忽略。我们自然会想到在SIGCHLD信号的处理函数中调用wait。于是:void sig_chld(int signo)int status;wait(,实例:SIGCHLD信号,当然我们还要设置SIGCHLD的处理函数:signal(SIGCHLD,sig_chld);好像已经大功告成,但实际上却存在问题。(程序演示)我们看到,系统中留下了很多僵死的进程,说明它们的退出状态并没有被回收,这是为什么?,实例:SIGCHLD信号,解答:前面说到,在信号处理过程中,相同的信号是被屏蔽的。也就是说,在sig

6、_chld过程中进程是不会再收到SIGCHLD信号的。被屏蔽的信号被保存下来,在sig_chld返回之后进程会收到被屏蔽的信号。但是,被屏蔽信号的保存是不排队的,也就是说,进程知道在信号屏蔽过程中有没有收到这个信号,而无法知道收到几个。,实例:SIGCHLD信号,结果:父进程只回收到了某些子进程的退出状态。解决办法:这样子改写sig_chld函数:void sig_chld(int signo)int status;while(waitpid(-1,进程间通信(IPC),著名Unix与网络专家Richard Stevens,有多本Unix著作,本本经典。Advanced Programming

7、 In the Unix Environment(APUE)TCP/IP Illustrated volume 1,2,3Unix Network Programming(UNP)volume 1,21999年9月30号去世TT,UNP volume 3没有写完。,进程间通信(IPC),UNP volume 2:用了一本书来讲IPC所以,我不可能在半节课之内涵盖IPC的各个方面,只能讲一些最基本,也是最重要的:管道通信FIFO通信,管道通信,最古老的Unix IPC工具,一个进程从管道一头写数据,另一个进程从管道另一头读数据。相通信方式是单向的。(演示shell下的管道通信)先了解一下进程创建

8、过程中文件描述字的继承。,单个进程打开两个文件,fork之后,管道通信,创建管道pipe函数原型:#include int pipe(int fdes2);pipe函数成功后,内核打开两个文件描述字fdes0,fdes1。fdes0输入端,fdes1为输出端。,当进程调用了pipe,fork被调用后,两个进程分别关闭一个端,int main(void)pid_t pid;int fdes2;if(pipe(fdes)0)close(fdes0);write(fdes1,“Hmmmmmmmmmmm”,12);/*1 2 3 4 5 6 7 8 9 0 1 2*/else char buf4096

9、;ssize_t n;close(fdes1)n=read(fdes0,buf,4096);if(n=0)bufn=0;printf(“%sn”,buf);return 0;,管道破裂,如果一个管道的读端已经关闭,进程还继续向写端写数据,如:pipe(fdes);close(fdes0);write(fdes1,“Let me die”,10);则进程会收到一个SIGPIPE信号,表示管道破裂。默认动作为结束进程。读一个写端已经关闭的管道则read返回0。,FIFO通信,FIFO是一种特殊设备文件,又称为有名管道。操作方法与普通文件相同。对于普通文件,我们可以从文件任一位置读数据,也可以从任一

10、位置写数据;数据读完不会消失。但对FIFO来说,我们只能从文件头读数据,从文件尾写数据。数据被某进程读走之后就会消失。(实例演示),FIFO相关的调用和shell命令,创建设备文件FIFO:mkfifo 函数原型:#include#include int mkfifo(const char*filename,mode_t mode);shell命令:$mkfifo m 0600 fifo1,线程简介,Linux下的clone系统调用可以实现比fork更多的功能,比如让创建出来的子进程分享父进程的地址空间。习惯上把这些与父进程分享地址空间的子进程称为线程(Thread)。不同的系统对线程有不一样

11、的定义,但相同之处是它比进程的开消小,因此也被称为是轻量级进程。,线程简介,因为地址空间共享使得线程之间的通信非常方便,但必须特别注意数据一致性。Posix定了标准的线程接口,请参考UNP volume 1,Chapter 23,高级IO,I/O的方式有很多种,我们之前使用的IO方式的特点是:单路:只能等待一个fd可读或可写阻塞:睡眠直到fd可读或可写同步:read和write必须结束才返回?因此有与之对应的:多路:同时等待多个fd可读或可写非阻塞:fd不可读或不可写立即返回异步:I/O没有结束read和write也可返回,非阻塞I/O,以非阻塞方式打开一个文件,如:fd=open(“love

12、.txt”,O_RDWR|O_NONBLOCK,0);也可以用fcntl让一个已经打开的文件描述字变成非阻塞:flags=fcntl(fd,F_GETFL,0);fcntl(fd,F_SETFL,flags|O_NONBLOCK);,非阻塞I/O,对一个非阻塞的fd来说,如果它无数据可读,则read(fd,);返回-1,errno的值被置为EAGAIN;同样,如果它暂时不可写,write(fd,);返回-1,errno=EAGAIN。(阻塞式I/O在这两种情况下都是等待)。注意:应当区为无数据可读与文件已经读到结尾。后者read返回0,无论阻塞否。非阻塞I/O经常与多路I/O配合使用。,多路I

13、/O,想像一个fd集合fdset,以及一个函数fun,我们指定:调用fun(fdset)进程进入睡眠,直到fdset中至少有一个fd可读,此时fun返回并把可读的fd保存在fdset中。这样做的好处是,我们可以同时从多个fd中等待数据,如果某一个可读我们就从中读取,否则就睡眠。,多路I/O,Unix下就存在这种的一个fun,但它的功能更加强大。它就是select(在有的系统下为poll,Linux都支持)函数原型:#include#include int select(int maxfdp1,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,struct timeval*timeout);,多路I/O,函数的声明太复杂。下面通过编写一个程序来综合的演示多路I/O,非阻塞I/O,以及FIFO。Lets go!,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号