最全的Linux教程,Linux从入门到精通
======================
-
linux从入门到精通(第2版)
-
Linux系统移植
-
Linux驱动开发入门与实战
-
LINUX 系统移植 第2版
-
Linux开源网络全栈详解 从DPDK到OpenFlow
第一份《Linux从入门到精通》466页
====================
内容简介
====
本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。
本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。
需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
/ \
/事件 \
过程(进程)2 /—v—
/
/
过程(进程)3 /— —\
信号是提供异步事件处理机制的软件中断。这些异步事件可能来自硬件设备,也可能来自系统内核,甚至可能来自用户程序。进程之间可以相互发送信号,这使信号成为一种进程间通信(Inter-Process Communication, IPC)的基本手段。信号的异步特性不仅表现为它的产生是异步的,对它的处理同样也是异步的。程序设计者不可能也不需要精确地预见什么时候触发什么信号,也同样无法预见该信号究竟在什么时候会被处理。一切尽在内核操控下异步地发生。
2)什么是信号处理?
每一个信号都有其生命周期:
产生:信号被生成,并被发送至系统内核
未决:信号被内核缓存,而后被递送至目标进程
递送:内核已将信号发送至目标进程
忽略 - 什么也不做。
捕获 - 暂定当前的执行过程,转而调用一个事先写好的信号处理函数,待该函数完成并返回后,再继续之前被中断的过程。
默认 - 既不忽略该信号,也不用自己定义处理方式,而是按照系统默认的方式予以响应。
激励(信号)->响应(信号处理)
3)信号的名称和编号
信号名称:形如SIGXXX的字符串或宏定义,提高可读性。
信号编号:整数
通过kill -l命令查看当前系统所支持的全部信号名称及其编号。
1~31,31个不可靠信号,也叫非实时信号。
34~64, 31个可靠信号,也叫实时信号。
共62个信号,注意没有32和33信号。
SIGHUP(1),控制终端关闭,终止
SIGINT(2),用户产生中断符(Ctrl+C),终止
SIGQUIT(3),用户产生退出符(Ctrl+),终止+转储
SIGBUS(7),硬件或内存对齐错误,终止+转储
SIGKILL(9),不能被捕获和忽略,终止
SIGSEGV(11),无效内存访问,终止+转储
SIGPIPE(13),向读端已关闭的管道写入,终止
SIGALRM(14),alarm函数设置的闹钟到期,终止
SIGTERM(15),可被捕获和忽略,终止
SIGCHLD(17),子进程终止,忽略
SIGIO(29),异步I/O事件,终止
举例:写一个死循环
#include <stdio.h>
#include <unistd.h>
int main(void) {
printf("PID: %d\n", getpid());
for (;;);
return 0;
}
kill -SIGQUIT 进程pid 进程pid …
kill -SIGQUIT -1 给所有进程发QUIT信号
### 2.捕获信号
#include <signal.h>
typedef void (\*sighandler\_t) (int);
|
函数指针
指向一个接受整型参数且无返回值的函数
设置针对特定信号的处理方式,即捕获特定的信号:
sighandler\_t signal(int signum, sighandler\_t handler);
成功返回原信号处理方式,失败返回SIG\_ERR(sighandler\_t类型的-1)。
signum - 信号编号
handler - 信号处理函数指针,也可以取以下值:
SIG\_IGN - 忽略信号
SIG\_DFL - 默认操作
…
// 定义信号处理函数
void sigint (int signum) {
SIGINT(2)信号的处理代码
}
…
// 捕获SIGINT(2)信号
if (signal(SIGINT, sigint) == SIG\_ERR) {
perror(“signal”);
return -1;
}
…
SIGINT(2)
v
SIGINT(2)/PID/sigint->系统内核
v
目标进程中的sigint函数
signal(SIGINT, SIG\_DFL); // 按默认方式处理
signal(SIGINT, SIG\_IGN); // 忽略信号
当一个信号正在被处理的过程中,相同的信号再次产生,该信号会被阻塞,直到前一个信号处理完成,即从信号处理函数中返回,后一个被阻塞的信号才被递送,进而再次执行信号处理函数。当一个不可靠信号正在被处理的过程中,多个相同的信号再次产生,只有第一个信号会被阻塞,其它信号直接丢弃,如果是可靠信号,都会被阻塞,并按照产生的顺序依次被递送。
信号处理函数及被其调用的函数都有可能发生重入,由此可能引发无可预知的风险。
global = 0;
…
++global;
…
所有标准I/O函数都是不可重入函数。在信号处理的过程中要慎用。
A信号->A信号处理函数 \ 打印AAAAAA
> printf(调试信息);
B信号->B信号处理函数 / 打印BBBBBB
AAABBBBBBAAA
代码:signal.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void sigint(int signum) {
signal(SIGINT, SIG_DFL);//一次性问题
printf("%d进程:收到%d信号!\n",
getpid(), signum);
signal(SIGINT, sigint);//不让系统出现一次性问题
}
void sigterm(int signum) {
printf("%d进程:收到%d信号!\n",
getpid(), signum);
printf("妥当善后...\n");
exit(0);
}
int main(void) {
if (signal(/\*2\*/SIGINT, sigint) == SIG_ERR) {
perror("signal");
return -1;
}
if (signal(/\*3\*/SIGQUIT, SIG_IGN) ==
SIG_ERR) {
perror("signal");
return -1;
}
if (signal(/\*9\*//\*SIGKILL\*//\*15\*/SIGTERM,
/\*SIG\_IGN\*/sigterm/\*SIG\_DFL\*/)==SIG_ERR){
//9信号不能被忽略,也不能捕获
perror(“signal”);
return -1;
}
for (;😉;
return 0;
}
### 3.信号捕获流程
中断
主控制流程--------- v ----------->
/
信号处理函数 / ------> \ 用户空间
/ \ / \ ---------
/ \ / \ 内核空间
内核处理流程-----------> ---------->
do_signal system_call
V V
handle_signal sys_sigreturn
V V
setup_frame restore_sigcontext
信号的本质是一个中断的处理过程,而非多线程的并发过程。
线程安全的函数未必是可重入函数。
V V
锁机制 局部化
### 4.信号捕获的一次性问题
在某些非Linux操作系统上,存在信号捕获的一次性问题:
即使设置了对某个信号的捕获,只有设置后的第一个该信号被递送时,信号处理函数会被执行,以后再来相同的信号,均按默认方式处理。如果希望对信号的捕获具有持久性,可以在信号处理函数返回前再次设置对该信号的捕获。
### 5.太平间信号
通过SIGCHLD(17)信号高效地回收子进程僵尸。
高效:及时性,适时性。
代码:sigchld.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
void sigchld(int signum) {
for (;;) {
//为了收集所有僵尸,故循环
pid_t pid = waitpid(-1, NULL, WNOHANG);//非阻塞
if (pid == -1) {
if (errno != ECHILD) {
perror("wait");
exit(-1);
}
printf("父进程:所有子进程"
"都已终止。\n");
break;
}
if (!pid) {
printf("父进程:暂时没有可回收的"
"子进程。\n");
break;
}
printf("父进程:%d子进程终止。\n", pid);
}
usleep(100000);//为了观察现象
}
int main(void) {
if (signal(SIGCHLD, sigchld) == SIG_ERR) {
perror("signal");
return -1;
}
for (int i = 0; i < 5; ++i) {
pid_t pid = fork();
if (pid == -1) {
最全的Linux教程,Linux从入门到精通
======================
-
linux从入门到精通(第2版)
-
Linux系统移植
-
Linux驱动开发入门与实战
-
LINUX 系统移植 第2版
-
Linux开源网络全栈详解 从DPDK到OpenFlow
第一份《Linux从入门到精通》466页
====================
内容简介
====
本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。
本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。
需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!