不要在原子上下文中休眠
禁止中断时,也不能休眠
要确保有进程能唤醒自己
4.休眠被唤醒之后仍要检查等待的条件是否为真,否则重新继续休眠.
我们休眠的代码必须能够唤醒(wake_up),我们需要维护一个称为等待队列的数据结构. 等待队列就是一个进程链表,其中包含了等待了某个特定事件的所有进程. linux维护一个”等待队列头”来管理,wait_queue_head_t,定义在<linux/wait.h>
这里结构体前面的”__“是系统调用的函数.
DECLARE_WAIT_QUEUE_HEAD(name)
色块内的是方法,这里,我把相关的代码放在了一起,以便于理解.
linux 中最简单的休眠方式是下面的宏:
wait_event(queue, condition); //uninterruptible sleep
wait_event_interruptible(queue, condition); //返回非0值表示 休眠被信号中断
在这两个Macro实现中,分别有一个might_sleep()
的使用.而且后者
在实现上比前者多了个int __ret = 0
;
wait_event_timeout(queue, condition, timeout);
wait_event_interruptible_timeout(queue, condition, timeout);
不得不说一下这个宏,上面这四个宏中都牵扯上它了.代码注释是这么说的:
might_sleep - annotation for function that can sleep
queue 是等待队列头,传值方式,condition是任意一个布尔表达式,在休眠前后多次 对condition求值,为真则唤醒.
void wake_up(wait_queue_head_t *queue);
void wake_up_interruptible(wait_queue_head_t *queue);
实际上,一般是wait_event
和wake_up,
wait_event_interruptible和
wake_
u_interruptible`成对使用
(linux 中关于信号的资源)![http://www.thegeekstuff.com/2012/03/linux-signals-fundamentals/]
资源(http://www.linuxprogrammingblog.com/all-about-linux-signals?page=3)
信号就是一个软中断(software interrupts)。 一个健壮的程序必须需要处理信号,信号是向应用程序传递异步事件的方式。
一个用户按下ctrl+c 就是向另一个程序发送信号
用户通过Crtl-C、Crtl-\等键或者通过驱动终端程序来请求内核产生信号。
当进程执行出错时,内核给进程发送一个信号,比如,非法存取段、浮点数溢出、 或者一个非法的机器指令。内核也利用信号通知进程特事件的发生。
一个进程可以通过系统调用kill给另一个进程发送信号。一个进程可以可以和另一个 进程通过信号通信。
由进程的某个操作产生的信号被称为同步信号,例如,被零除;像用户击键这样的进程外 的事件引起的信号称之为异步信号。
使用以下调用来恢复默认处理
signal(SIGINT, SIG_DFL);
这是这类信号处理行为的最普遍的,有SIGTERM、SIGQUIT、SIGPIPE、SIGUSR1、SIGUSR2
有SIGSEGV、SIGILL、SIGABRT这个信号。
比如这个SIGCHLD
SIGSTOP使进程悬停(suspend)然后使用SIGCOND继续(shell中的ctrl-z)
程序可以通过以下调用来告诉内核,它需要忽略SIGINT的信号
signal(SIGINT, SIG_IGN);
如果产生像除以0的致命错误、SIGKILL和SIGSTOP不能被忽略。
后两个信号供root用户拥有杀死任何进程的权利。
程序在接收到SIGINT后,调用一个恢复设置的函数
signal(SIGALRM, handler);
补充一下最后一点,捕捉信号的函数应该是可重入的。在解释这个原因前,让我们首先了解下什么是可重入。一个可重入的函数是一个函数在执行的过程的可以因为某些原因被停止下来(比如中断或者信号),在完成了某项任务后可以返回继续执行原来的程序。原因很简单,当一个程序正在执行的时候,信号发生(捕捉另一个信号),进程转而执行其他的程序,如果这个时候正好宿主程序的全局变量和被呼叫的程序的变量同名的话,那么,当子进程执行完毕后返回宿主进程中,会产生意想不到的结果
可靠信号就是实时信号
非可靠信号就是非实时信号,凡位于[SIGRTMIN, SIGRTMAX]区间的都是可靠信号.
非可靠信号一般都有明确的用途和含义,可靠信号则可以让用户自己定义使用.
#include<signal.h>
void (*signal(int signum, void (*handler))(int))(int);
套接字(socket)是一种为计算机网络通信编程的接口,首次出现在美国加州Berkeley大学开发的BSD版本的系统中.有了套接字(应用层),从而允许我们进行服务器/客户端的开发,不必关心底层的细节.详细的关于内核网络协议的实现,我会在以后详细阐述,现在,这篇文章
` domain`: 代表套接字地址族,常用的有AF_INET,PF_INET(IPv4),AF_INET6(IPv6), AF_IPX(Novell 网络协议)…
type
: 最常用的是SOCK_STREAM和SOCK_DGRAM,分别表示流式套接字和数据包套接字.
protocol
: 一般情况下会设置为0,表示由系统在当前的domain下选择合适的协议.
TODO
#1
首先是APUE,patch和little,加油
#2
在本网站的首页为什么会遇到这样的问题呢,多显示了三个日期,然而,本地测试一点问题没有的