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. box-shadow做出一条线两种颜色

    今天同事问我一个问题,说下图的效果是怎么实现的 我当时想都没有想说这不就是两条线嘛,他说是一条线用box-shadow做出来的,之前也没有遇到过,觉得很有意思就试了一把. 语法 box-shadow: ...

  2. linux ar命令参数及用法详解--linux建立、修改或抽取备存文件命

    功能说明:建立或修改备存文件,或是从备存文件中抽取文件. 语 法:ar[-dmpqrtx][cfosSuvV][a<成员文件>][b<成员文件>][i<成员文件>] ...

  3. Flink实战(1) - Apache Flink安装和示例程序的执行

    在Windows上安装 从官方网站下载需要的二进制包 比如我下载的是flink-1.2.0-bin-hadoop2-scala_2.10.tgz,解压后进入bin目录 可以执行bat文件,也可以使用c ...

  4. Scrapy、Scrapy-redis组件

    目录 Scrapy 一.安装 二.基本使用 1. 基本命令 2.项目结构以及爬虫应用简介 3. 小试牛刀 4. 选择器 5. 格式化处理 6.中间件 7. 自定制命令 8. 自定义扩展 9. 避免重复 ...

  5. oracle note

    null null为无效的,未指定的,未知的活不可预知的值 null不是空格或0 包含null 的数学表达式其结果都为空值 null 永远!= null 判断某个字段为null,用 ename is ...

  6. Git图形化界面客户端

    Git图形化界面客户端大汇总 文,还在不断更新,网上搜到的同名文章都是未经同意就从这里复制过去的) 一.TortoiseGit - The coolest Interface to Git Versi ...

  7. sedsed 一个更好理解sed执行过程的工具

    官网:http://aurelio.net/projects/sedsed/    这个上面好多学习的资料 嘿嘿 留着慢慢看 昨晚在看sed的具体执行过程,看到有hold space,pattern ...

  8. vue+elementui按需引入

    转载自以下网址,仅作备忘之用:https://www.cnblogs.com/lwj820876312/p/9169457.html 基于Vue的Ui框架 饿了么公司基于vue开的的vue的Ui组件库 ...

  9. 让所有浏览器支持HTML5 video视频标签

    HTML5究竟需要多少种视频编码格式 当前,video 元素支持三种视频格式:Ogg = 带有 Theora 视频编码和 Vorbis 音频编码的 Ogg 文件MPEG4 = 带有 H.264 视频编 ...

  10. centos 7.x开放端口

    1. 查看已打开的端口 # netstat -anp 2. 查看想开的端口是否已开 # firewall-cmd --query-port=666/tcp 若此提示 FirewallD is not ...