1、基本概念

进程阻塞:

进程执行条件得不到满足,就自动放弃CPU资源而进入休眠状态,以等待条件满足,当条件满足时,系统就将控制权还给该进程进行未完成的操作

共享资源:

进程间协调使用的系统资源

锁定:

当某个进程使用共享资源时,可能需要防止别的进程对该资源的使用。Linux提供一些方法保证共享资源被某个进程使用时,其他进程不能使用,就称为共享资源的锁定

2、信号

信号的作用是通知一个或多个进程异步事件的发生,也可以用来处理某种严重的错误,可以从内核发往进程,也可以从一个进程发往另一个进程,

例如:用户在后台启动了一个程序,现在想要终止此进程的执行,就可以使用Kill命令将SIGTERM信号发送给这个进程,SIGTERM将终止该进程的执行

例如:执行exit()时,就向子进程的父进程发送SIGCHLD信号(子进程结束信号),若此时父进程在执行wait(),则父进程会被唤醒,若不是在执行wait(),则此父进程不会捕捉到SIGCHLD信号,该信号就不起作用,子进程进入过渡状态(如果父进程忽略SIGCHLD,子进程就会结束而不会进入过渡状态)

在大多数情况下,当进程收到一个信号时,会被正常终止,相当于进程执行了一个临时加入的exit()调用。

信号SIGQUIT、SIGILL、SIGTRAP、SIGFPE会导致一个非正常终止,它们将发生核心转贮,也就是把进程的内存映像写入进程当前目录的core文件中,core文件以二进制形式记录了终止时程序中全部变量值、硬件寄存器值和内核中的控制信息,非正常终止进程的退出状态除了其低端第7位置位外,其他与通过信号正常终止时一样

3、信号的复位

当一个信号的信号处理函数执行时,该进程又收到了同样的信号,那么该信号将会被存储而不会中断信号处理函数,直到信号处理函数执行完后重新调用相应处理函数,但是如果接收到了其他类型的信号,那么该信号处理函数将会被中断

例如:

#include <signal.h>
int interrupt()
{
printf(“Interrupt called\n”);
sleep(3);
printf(“Interrupt Func Ended.\n”);
}
main()
{
signal(SIGINT,interrupt);
printf(“Interrupt set for SIGINT\n”);
sleep(10);
printf(“Program NORMAL ended.\n”);
return;
}

  执行结果就是

Interrupt set for SIGINT
<ctrl+c>
Interrupt called
<ctrl+c>
Func Ended
Interrupt called
Func Ended
Program NORMAL ended.

  而代码:

#include <signal.h>
int interrupt()
{
printf(“Interrupt called\n”);
sleep(3);
printf(“Interrupt Func Ended.\n”);
}
int catchquit()
{
printf(“Quit called\n”);
sleep(3);
printf(“Quit ended.\n”);
}
main()
{
signal(SIGINT,interrupt);
signal(SIGQUIT,catchquit);
printf(“Interrupt set for SIGINT\n”);
sleep(10);
printf(“Program NORMAL ended.\n”);
return;
}

  执行的结果是

Interrupt set for SIGINT
<ctrl+c>
Interrupt called
<ctrl+\>
Quit called
Quit ended.
Interrupt Func Ended.
Program NORMAL ended.

  还有就是同一种信号不能累积,如:

Interrupt set for SIGINT
<ctrl+c>
Interrupt called
<ctrl+c><ctrl+c><ctrl+c>
Func Ended
Interrupt called
Func Ended
Program NORMAL ended.

  如果两个信号同时产生,系统不保证进程接收的顺序,因此,信号处理的顺序就不可控

4、进程间发送信号

一个进程可以通过signal()调用来处理其他进程发送来的信号,同时也可以通过kill(pid_t pid,int sig)来向其他进程发送信号。pid指定了信号发送的对象进程。可以是进程标识符,也可以是以下的值

1)pid = 0,  则信号被发送到当前进程所在的进程组的所有进程

2)pid = -1, 则信号按进程标识符从高到低的顺序发送给全部的进程

3)pid < -1,则信号被发送给标识符为pid 绝对值的进程组里的所有进程

信号发送的限制:普通用户进程只能向具有与其相同的用户标识符的进程发送信号,也就是说一个用户的进程不能向另一个用户的进程发送信号,只有root用户的进程才能给任何进程发送信号。

由于Kill需要知道目标进程标识符,所以一般在父子进程之间进行信号发送

举个例子:两个进程,通过发送SIGUSER1实现同步,两个进程都处于死循环中,接收对方信号前,处于暂停等待中,也就是pause(),使得程序暂停一直到信号达到,然后进程输出信息,并用kill发送一个信号给对方,若用户按了中断键,两个进程终止

#include <signal.h>
int ntimes = 0;
main()
{
int pid,ppid;
int p_action(), c_action();
/* 设定父进程的SIGUSR1 */
signal(SIGUSR1,p_action);
switch(pid = fork())
{
case -1: /*fork 失败*/
perror("synchro");
exit(1);
case 0: /*子进程模块*/
/* 设定子进程的SIGUSR1 */
signal(SIGUSR1,c_action);
/* 获得父进程的标识符 */
ppid = getppid();
for(;;)
{
sleep(1);
kill(ppid,SIGUSR1);
pause();
}
/*死循环*/
break;
default: /*父进程模块*/
for (;;)
{
pause();
sleep(1);
kill(pid,SIGUSR1);
}
/*死循环*/
}
}
int p_action()
{
printf("Patent caught signal #%d\n",++ntimes);
}
int c_action()
{
printf("Child caught signal #%d\n",++ntimes);
}

  运行结果就是

Patent caught signal #1
Child caught signal #1
Patent caught signal #2
Child caught signal #2
Patent caught signal #3
Child caught signal #3
Patent caught signal #4
Child caught signal #4
<ctrl+c>

  

Linux网络编程学习(五) ----- 信号(第四章)的更多相关文章

  1. Linux网络编程学习(六) ----- 管道(第四章)

    1.管道的定义 管道就是将一个程序的输出和另外一个程序的输入连接起来的单向通道,比如命令: ls -l|more,就建立了一个管道,获取ls -l的输出作为more的输入,数据就沿着管道从管道的左边流 ...

  2. Linux网络编程学习(十) ----- Socket(第六章)

    前言:由于第五章主要介绍了TCP和UDP协议以及两者的包头的字段以及相应的功能,这里就不介绍了,对着字段看功能就好了,后续开始学习第六章 1.Socket Socket实质上就是提供了通信的端点,每个 ...

  3. Linux网络编程学习计划

    由于网络编程是很重要的一块,自己这一块也比较欠缺,只知道一些皮毛,从今天开始系统学习<Linux网络编程>一书,全书分为十四个章节: 第一章   概论   P1-16 第二章   UNIX ...

  4. Linux网络编程学习路线

    转载自:https://blog.csdn.net/lianghe_work/article 一.网络应用层编程   1.Linux网络编程01——网络协议入门 2.Linux网络编程02——无连接和 ...

  5. Linux网络编程学习(十二) ----- 结语

    该书提前看完了,重点看了第四章和第六章,第七章以后只是大致浏览了一下,如果以后工作中涉及这一块再仔细研究一下,大概花了二十天的样子,主要了解了进程间的通信方式.socket编程以及五种I/O模式,看的 ...

  6. Linux网络编程学习(九) ----- 消息队列(第四章)

    1.System V IPC System V中引入的几种新的进程间通信方式,消息队列,信号量和共享内存,统称为System V IPC,其具体实例在内核中是以对象的形式出现的,称为IPC 对象,每个 ...

  7. Linux网络编程学习(十一) ----- 五种I/O模式(第六章)

    1.五种I/O模式是哪几个? 阻塞I/O,非阻塞I/O,I/O多路复用,信号驱动I/O(SIGIO),异步I/O 一般来讲程序进行输入操作有两个步骤,一是等待有数据可读,二是将数据从系统内核中拷贝到程 ...

  8. Linux网络编程学习(七) ----- 有名管道(第四章)

    1.什么是有名管道?为什么有了管道还需要有名管道? 有名管道是解决管道不能提供非父子进程间通信的缺陷.管道在Linux系统内部是以文件节点(inode)的形式存在,但由于其对外的不可见性(“无名”性) ...

  9. Linux网络编程学习(四) -----守护进程的建立(第三章)

    本文介绍一个例程daemon_init() #include <sys/types.h> #include <signal.h> #include <unistd.h&g ...

随机推荐

  1. Mysql 复制一个新表

    1.复制表结构及数据到新表CREATE TABLE 新表 SELECT * FROM 旧表这种方法会将oldtable中所有的内容都拷贝过来,当然我们可以用delete from newtable;来 ...

  2. yarn依赖管理工具的使用

    Yarn是Facebook发布的一款依赖管理工具,它比npm更快.更高效. 与NPM命令对照 npm install => yarn install npm install --save [pa ...

  3. scanf连续输入字符,中间不要忘记\n

    #include <stdio.h> int main(void) { int precipitating; int temperature; printf("\nInput p ...

  4. CSS精简工具——除去多余的css样式

    有时候开发网页中在改版之后,存在很多无意义的样式,对于后期的管理和维护很不友好. 如果手动去删除,很可能会导致出现更混乱的问题. 最近找到一个Chrome插件,CSS remove and combi ...

  5. Unity打开外部程序exe/Bat文件方案

    Unity调用外部程序/Bat文件 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- ...

  6. 前端基础----CSS语法、CSS四种引入方式、CSS选择器、CSS属性操作

    一.CSS语法 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明. 例如: h1 {color:red; font-size:14px;} 二.CSS四种引入方式 1,行内式 行内式是在标 ...

  7. 缓慢拒绝服务攻击- slowloris.pl

    How use Slowloris   Requirements: # sudo apt-get update # sudo apt-get install perl # sudo apt-get i ...

  8. mongodb分片balance

    查看balance状态 mongos> sh.getBalancerState()true   通过balance锁查看balance活动 如果state是2,表示balance锁已经被获取 m ...

  9. 冒号课堂 编程范式与OOP思想

    上篇:编程范式与编程语言 第1课 开班导言 第2课 重要范式 第3课 常用范式 第4课 重温范式 第5课 语言小谈 第6课 语言简评 下篇:抽象机制与对象范式 第7课 抽象封装 第8课 抽象接口 第9 ...

  10. Feign中使用hystrix

    Feign中使用hystrix 一.在Order工程中的bootstrap.yml中增加配置 feign: hystrix: enabled: true