UNIX环境编程——信号篇下

UNIX环境高级编程重点复习 文章目录名词解释题简答题程序题书上例程读程序写结果改错写程序论文《The Three Pillars of Machine Programming》相关论文《pix2code: Generating Code From a Graphical User》、sketch2code相关小组项目相关 名词解释题 1.内核(kernel): 内核是一种软件,它控制计算机硬件资源,提供程序运行环境。内核通常... 阅读详情
发送
  1. 键盘

    • ctrl + c SIGINT
    • ctrl + \ SIGQUIT
    • ctrl + z SIGTSTP
  2. 错误

    • 除0 SIGFPE(8)
    • 非法内存访问 SIGSEGV(11)
    • 硬件故障 SIGBUS(7)
  3. 命令

    • kill -信号 进程
  4. 函数

    • kill

      #include <signal.h>
      
      int kill(pid_t pid,int sig);
      向pid进程发送sig信号,成功返回0,失败返回-1
      pid取值:
      	> 0   - 向pid进程发送sig信号
          = 0   - 向同进程组中所有进程发送信号
          = -1  - 向所有进程送信号    前提是调用进程有向其发送信号的权限
          < -1  - 向绝对值小于|pid|的进程组发送信号
      
      sig取值:
      	0信号为空信号,则kill函数仍会执行错误检查,但实际上并不会发送信号,经常用来检测确定一个进程是否存在
          >0 正常发送信号
          向一个不存在的进程发送信号,会返回-1,且errno为ESRCH
      
    • raise

      #include <signal.h>
      
      int raise(int sig);
      //向调用进程自身发送sig信号,成功返回0,失败返回-1
      
    • pause/sleep

      #include <unistd.h>
      
      int pause(void);
      unsigned int sleep(unsigned int seconds);
      
      int usleep(useconds_t usec); //微秒
      
      • 使调用这个函数的进程进入睡眠状态,直到被信号终止或者`捕获
      • 只有调用了信号处理函数并从此乃好处理函数中返回以后,该函数才会返回
      • 该函数要么不返回,要么返回-1,errno设置为ENINTR
      • 相当于没有时间限制的sleep
      • sleep函数是的调用进程睡眠seconds秒, 除非有信号终止或者捕获
      • 该函数要么返回0(完全睡够了seconds秒),要么返回剩余未睡眠的秒数(被信号中断)
      • 相当于有时间限制的pause
    • alarm

      #include <unistd.h>
      
      unsigned int alarm(unsigned int seconds);
      
      • 使内核在seconds秒之后,向调用进程发送SIGALRM(14)闹钟信号

      • SIGALRM信号的默认处理方式是终止进程

      • 若之前已设置过alarm但时间还未到,又重新调用alarm函数会重新设置定时,并返回之前定时剩余的秒数

      • seconds参数取0时表示取消之前设过但未超时的定时

信号集

sigset_t 信号集类型 信号集

  • 多个信号的集合类型

  • 128个二进制位, 16byte, 每一个二进制位代表一个信号

  • 处理信号集需要函数

    #include <signal.h>
    
    int sigemptyset(sigset_t *set);   //把信号集中的信号全部清空 
    int sigfillset(sigset_t *set);    //将信号集中全部的位置1   把所有信号都添加到信号集中
    int sigaddset(sigset_t *set,int signum); //将信号signum添加到信号集中
    int sigdelset(sigset_t *set,int signum); //将信号signum从信号集中删除
    //成功返回0   失败返回-1
    int sigismember(const sigset_t *set,int signum);  //判断signum是否在set信号集中
    //如果signum在set信号集中返回1    否则返回0
    
信号屏蔽
  • 当每个进程都有一个信号掩码(signal mask

    • 信号掩码是一个信号集,其中包括所有需要屏蔽的信号
  • 当进程执行诸如更新数据可等铭感任务时,可能不希望被某些信号中断,因此就会屏蔽这些信号。

  • 屏蔽!=忽略

    • 屏蔽信号是指让信号处于未决状态,忽略是指捕获信号但不处理(进程依然被中断了)
  • 当信号产生时,系统内核就会在为其维护的进场表中,位特定的进程设置一个该信号的标志位,这个过程称为递送

  • 信号从产生到完成递送存在一定的时间间隔,出于这段时间的信号状态称为未决状态

  • 处于未决状态的信号,当取消屏蔽后会被递送,

  • 可以通过sigprocmask函数,检测和修改调用进程的信号掩码

  • 可以通过sigpending函数,获取调用进程当前处于未决状态的信号集

#include <signal.h>

int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);
成功返回0,失败返回-1
    
how		- 修改信号掩码的方式
    SIG_BLOCK: 新掩码是当前掩码和set的并集         把set信号集中的所有信号加入到信号掩码中
    SIG_UNBLOCK: 新掩码是当前掩码和set补集的交集    从信号掩码中删除在set信号集中的所有信号
    SIG_SETMASK: 把set设置为新的信号掩码
        
set		- 输入参数  信号集
    NULL 忽略

oldset	- 输出参数   备份以前的信号掩码,处理完之后好恢复原样,如果取NULL则不备份
        
        
int sigpending(sigset_t *set);
获取调用进程当前处于未决状态的信号集
    成功返回0,失败返回-1
    set作为输出参数
  • 对于不可靠信号,通过sigprocmask函数设置信号掩码之后,相同信号只会频闭第一个,并且在回复喜好掩码后被递送,其余的直接丢弃
  • 对于可靠信号,则会在信号屏蔽时暗器产生的先后栓徐排队,一旦恢复信号掩码,会依次被处理
  • 在信号处理函数中,实际上是自动屏蔽当前信号
sigaction/sigqueue
  • sigaction

    #include <signal.h>
    //功能作用signal  只是功能比signal要更加强大
    int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);
    //注册signum信号的信号处理方式为act,之前的处理方式通过oldact输出   oldact可以为NULL
    成功返回0   失败返回-1 
        
    struct sigaction{
        void (*sa_handler)(int);                         //信号处理函数指针1  兼容signal
        void (*sa_sigaction)(int,siginfo_t *,void *);    //信号处理函数指针2
        sigset_t sa_mask;                                //信号掩码   调用信号处理函数时屏蔽的信号集
        int sa_flags;                                    //信号处理标志
        void (*sa_restorer)(void);                       //保留  NULL
    };
    
    typedef struct siginfo{
        pid_t    si_pid;                        //发送信号的进程
        sigval_t si_value;                      //信号附加值(需要配置sigqueue函数)
        ....
    }siginfo_t;
    
    //发送信号时附加值
    typedef union sigval{
        int sival_int;
        void *sigval_ptr;//附加值如果是指针,只有在本进程中才有意义
    }sigval_t;
    
    
    • 缺省情况下,在信号处理函数的执行过程中,会自动屏蔽这个正在处理的信号,而对于其他信号则不会屏蔽,通过sigaction::sa_mask成员可以自行指定
      • 在信号处理函数的执行过程中,会把sa_mask信号集中的信号加入信号掩码中
      • 并且在信号处理函数执行完成后,自动解除sa_mask中信号的屏蔽
    • sa_flag信号处理标志,可以是以下的值
      • SA_ONESHOT/SA_RESETHAND
        • 执行完一次信号处理函数后,即将对引信号的处理恢复为默认方式
      • SA_NODEFER/SA_NOMASK
        • 在信号处理函数执行过程中,不屏蔽这个正在处理的信号
      • SA_NOCLDSTOP
        • 若signum参数取SIGCHLD,则当子里程暂停时,不通知父进程
      • SA_RESTART
        • 系统调用一旦被signum参数所表示的信号中断,会自行重启
      • SA_SIGINFO
        • 使用信号处理函数指针2 sa_sigaction,通过该函数的第二个参数,提供更多的信息
  • sigqueue

    #include <signal.h>
    
    int sigqueue(pid_t pid,int sig,const union sigval value);
    //向进程pid发送sig信号并且携带附加值value
    
    成功返回0,失败返回-1
        
    
计时器
  • 系统为每个进程维护三个计时器

    • 真实计时器
      • 程序运行的实际时间
    • 虚拟计时器
      • 程序运行在用户态所消耗的时间
    • 实用计时器
      • 程序运行在用户态和内核态所消耗的时间之和
  • 实际时间 == 用户态时间(虚拟计时器)+ 内核时间 + 睡眠时间 + 其他等待

  • 三个计时器发送的时钟信号分别为

    • SIGVLRM - 真实计时器
    • SIGVTALRM - 虚拟计时器
    • SIGPROF - 实用计时器
  • 可以用setitimer为进程设定好计算器,计时器会定时向进程发送时针信号

getitimer

获取计时器

setitimer

设定计时器

#include <sys/time.h>

int getitimer(int which,struct itimerval* curr_value);
//获取计时器设置,成功返回0,失败返回-1

int setitimer(int which,const struct itimerval *new_value,struct itimerval *old_value);
//设置计时器,成功返回0,失败返回-1

参数:
	which	- 指定哪个计时器
        ITIMER_REAL    - 真实计时器
        ITIMER_VIRTUAL - 虚拟计时器
        ITIMER_PROF    - 实用计时器

struct itimerval{
	struct timeval it_interval;  //重复间隔(每两个时针信号的时间间隔)   取0,只发送一个时钟信号
    struct timeval it_value;     //初始间隔   设置计时器之后多久产生第一个时针信号
};

struct timeval{
  	long tv_sec;    //秒数
    long tv_usec;   //微秒数
};

守护进程
进程组
  • 进程除了进程标识以外, 还有一个进程组标识,进程组ID

  • 进程组是一个或多个进程的集合

  • 进程组ID是取自一个进程的ID 一般来说是同一个进程内创建的子进程都会同属父进程的进程组中

    pid_t getpgrp(void);         //POSIX   获得调用进程的进程组ID
    pid_t getpgrp(pid_t pid);    //BSD     获取pid进程的进程组ID
    
    int setpgrpid(pid_t pid,pid_t gpid);  //给进程pid设置进程组ID为gpid
    
    
创建
  • 守护进程(daemon)是生存周期长的一种进程
    • 往往是操作系统引导装入时启动,仅在系统关闭时终止
    • 没有控制终端,在后台运行
  • 基本规则(防止不必要的交互)
    • 首先是 调用umask将文件权限屏蔽字设置为一个已知的值(通常为0)
      • 继承自父进程的权限往往会屏蔽一部分权限
    • 调用fork()创建子进程,父进程exit
      • 如果守护进程是作为简单的shell命令启动的,那么父进程终止会让shell认为命令已经执行完毕,
      • 虽然子进程继承了父进程的继承组ID,但获得了一个新的进程ID,这就保证了子进程不是一个进程组的组长,那么就可以用setsid来创建一个新绘画
    • 调用setsid()函数,让当前进程成为新会话的首进程
      • 成为了新进程组的组长
      • 没有控制终端
    • 将当前工作路径更改为根目录
      • 保证父进程退出后,能够确保在一个有效的文件系统中
      • 当然可以根据需要切换至指定目录
    • 关闭没有必要的文件
      • close(0) close(1) close(2)
      • 某些守护进程打开/dev/null使其具有文件描述符0,1,2这样一个试图读写标准输入、标准输出的代码不会有任何的错误
//创建守护进程执行cmd命令
void daemon(const char *cmd){
    umask(0);
    pid_t id = fork();
    if(id == -1){
        return;
    }
    if(id != 0){
        exit(0);
    }
    setsit();    
    chdir("/");
    //close(0);close(1);close(2);
    /*
    struct rlimit rl;
    if(getrlimit(RLIMIT_NOFILE,&rl) < 0)
        return;
   	if(rl.rlim_max == RLIM_INFINITY)
        rl.rlim_max = 1024;
    */
    int i;
    for(i=0;i</*rl.rlim_max*/1024;++i){
        close(i);
    }
    //执行守护进程的任务
    system(cmd);
}
会话
  • 会话是一个或多个进程组的集合
  • 如果调用stesid的进程不是一个进程组的组长,则此函数创建一个新会话,具体的实用如下
    1. 该进程变成新会话 的会话首进程,该进程会是该进程的唯一进程
    2. 该进程称为一个新进程组的组长
    3. 该进程没有控制终端,如果在调用setsid之前,该进程有一个控制终端,那么此后会切断这种连系,为了摆脱控制终端的控制,终端关闭也不会被杀死
#include <unistd.h>
pid_t getsid(pid_t pid);
	若成功,返回会话首进程的进程组ID,若出错返回-1
    pid若为0,获取当前调用getsid()函数的进程的会话首进程的进程组ID    相当于给了getpid()
    出于安全考虑,若参数pid并不属于调用者所在的会话,可能获取不到

pid_t setsid(void);  //创建一个新session  
UNIX环境高级编程》笔记 第十五章-进程间通信 1. 匿名管道 匿名管道是UNIX系统IPC(进程间通信)最古老的方式,所有UNIX系统都提供这种通信机制 匿名管道有以下局限性: 历史上,它们是半双工的(数据只能在一个方向上流动)。现在某些操作系统提供全双工匿名管道,但是为了可移植性,应该按照半双工来进行编程 管道只能在具有公共祖先的两个进程间使用。通常一个管道由一个进程创建,在进程fork之后,父子进程之间通过该管道进行通信。 命名管道(FIFO)没有第二种限制,UNIX域套接字没有这两种限制 1.1 pipe函数 通过pipe函数创建管道 int 阅读详情

相关推荐

unixunix环境高级编程

一 创建 ⑴线程命名规则 nioEventLoop-1-XX -1指的是线程池 -XX在group中的loop 创建并保存线程执行器 创建mpscQueue异步任务队列 创建线程选择器,循环nioEventLoop数组 二 启动 1.服务端启动绑定端口 2.新连接接入 三 执行 一个普通任务队列 一个定时任务队列 任务聚合时会把定时任务队列拉去到普通任务队列,保证串行无锁化 四 亮点 ⑴ ⑵ha...

屎蛋的铲屎官 1667

UNIX 环境高级编程》学习笔记——线程控制

UNIX环境高级编程——线程控制引言线程限制线程属性同步属性互斥量属性读写锁属性条件变量属性屏障属性重入线程特定数据取消选项线程和信号线程和 fork线程和 I/O小结 引言 线程限制 PTHREAD_DESTRUCTOR_ITERATIONS 线程退出系统时试图销毁线程特定数据最大次数 _SC_THREAD_DESTRUCTOR_ITERATIONS PTHREAD_KEYS_MAX 进程可创建键的最大次数 _SC_THREAD_KEYS_MAX PTHREAD_STACK_MIN

weixin_45243288的博客 319

unix高级环境编程信号——abort、system和sleep函数

abort函数   abort函数的功能是使异常终止,此函数将SIGABRT信号发送给调用进程,让进程捕捉SIGABRT信号目的是在进程终止之前由其执行所需的清理操作。默认情况是终止调用进程。可以采用sigaction和kill函数来实现abort,程序如下: system函数   POSIX.1要求system函数忽略SIGINT和SITQUIT信号,阻塞SIGCHLD。采

关注校招求职,微信号:job_campus 1585

unix环境高级编程信号(一)

一、引言: 信号是软件中断,很比较重要的应用程序都需要处理信号信号提供了一种处理异步事件的方法,例如,中断用户键入中断键,则会通过信号机制停止一个程序,或及早终止管道中的下一个程序。

愤怒的呆鱼 1358

unix环境高级编程信号(二)

一、引言: 信号是软件中断,很比较重要的应用程序都需要处理信号信号提供了一种处理异步事件的方法,例如,中断用户键入中断键,则会通过信号机制停止一个程序,或及早终止管道中的下一个程序。

愤怒的呆鱼 544

量化交易之linux - 《UNIX环境高级编程》 - 捕捉信号SIGINT

#include "apue.h" #include <stdio.h> #include <dirent.h> #include <sys/wait.h> static void sig_int(int value); // signal catching function int main(int argc, char* argv[]) { char buf[MAXLINE]; pid_t pidl int status; if.

192

UNIX环境高级编程笔记

UNIX advanced environment programming notes 文章目录UNIX advanced environment programming notescase 1: shell ls ???? Consult the function, user man page   case 1: shell ls #include <stdio.h> #include <sys/types.h> #include <dirent.h> int mai

qq_31507523的博客 466

Linux环境编程Day01

程序员必备技能: 一门编程语言:C语言、C++ 数据结构与算法:表、树、图、查找、排序、STL 操作系统:UNIX/Linux系统 网络编程:TCP\IP(Socket技术、TCP、UDP、FTP协议) 数据库:MySQL 界面设计:Qt 课程介绍: 环境介绍 内存管理 文件管理 信号处理 进程管理 进程通信 线程管理 线程同步 网络编程 UNIX...

weixin_53854228的博客 268

C++学习–应用(Windows/Linux)(书籍推荐及分享)

我将以平台划分,分别介绍Windows和Linux下个人认为的好书(与基础一样,大部分都提供有电子版); 对于C++基础类的图书,这里不再重复,有兴趣的朋友请移步《C++学习–基础》。 Windows: 在Windows平台下主要说的是VC编程(使用MFC),以下将对VC开发的相关图书介绍;对于ATL等,涉及不多,不做评论;   《Windows程序设计》

lijun5635的专栏 994

unix环境高级编程 第三版 pdf 中文版_UNIX环境高级编程——信号

引言今天读完《UNIX环境高级编程》第10章信号,这一章对UNIX系统的信号相关的函数进行了解释。信号信号是用来中断进程的执行(与底层的CPU级别的中断相似,但一个是中断CPU的执行,一个是中断进程的执行)。信号机制信号的使用在使用一个信号时,我们首先需要知道该信号是如何产生的,是由一些异常产生的(如除0),还是手工产生的(如kill, alarm等)。在知道了信号如何产生后,我们就需要为进程注册...

weixin_39631667的博客 2418

UNIX 环境高级编程(第 3 版)》剖析

UNIX 环境高级编程(第 3 版)》作为 UNIX 编程领域的经典之作,不仅涵盖了 UNIX 系统编程的各个方面,还通过大量的代码示例和深入的讲解,帮助读者深入理解 UNIX 系统的底层机制,掌握编写高效、可移植的 UNIX 应用程序的技巧。无论是对于初学者还是有一定经验的开发者,本书都具有极高的学习价值和参考价值。随着技术的不断发展,UNIX 系统也在不断演进,新的特性和功能不断涌现。

数字魔方操控师的博客 1067

UNIX环境高级编程(中文版)

UNIX系统的架构主要由内核和用户空间两部分组成。内核是操作系统的核心,负责管理系统资源、进程调度、内存管理和设备控制等。用户空间则是用户程序运行的环境,用户在这里执行应用程序并与系统进行交互。在上述代码中,我们使用open系统调用创建了一个名为的文件,并设置了文件的权限。接着,我们使用write系统调用将字符串“Hello, UNIX!”写入文件。最后,通过close系统调用关闭文件描述符,释放资源。在上述代码中,我们使用fork系统调用创建了一个新进程。fork。

csdn_te_DOWNload_005的博客 1618

UNIX 环境高级编程》学习笔记——信号

UNIX环境高级编程——信号引言信号概念函数 signal不可靠的信号中断的系统调用可重入函数可靠信号术语和语义函数 kill 和 raise函数 alarm 和 pause信号集函数 sigprocmask函数 sigpending函数 sigaction函数 sigsuspend函数 abort函数 sleep、nanosleep 和 clock_nanosleep函数 sigqueue 引言 信号概念 - SIGABRT abort产生 - SIGALRM alarm设置的时间到达 - SIGCHLD

weixin_45243288的博客 678

UNIX环境编程——信号

本期主题: 信号 往期地址: UNIX环境编程——文件IO UNIX环境编程——标准IO UNIX环境编程——进程环境与进程控制 unix高级环境编程——线程详解 unix环境高级编程——UNIX体系架构 文章目录1.信号概念2.信号操作1.发送信号2.接收信号 1.信号概念 信号UNIXLinux系统响应某些条件而产生的一个事件,用来通知进程系统中发生了某种类型的事件。 用术语生成(raise)表示一个信号的产生,使用术语捕获(catch)表示接收到一个信号。 有很多条件都可以产生信号

weixin_37620587的博客 307

UNIX 环境高级编程》核心思想讲座课件

被誉为UNIX编程"圣经"的经典著作作者:W. Richard Stevens和Stephen A. Rago第1版(1992年)、第2版(2005年)、第3版(2013年)的演进Dennis Ritchie(UNIX和C语言之父)评价:“这是一本弥足珍贵的经典著作”进程间通信的需求与挑战UNIX/Linux中的IPC机制分类IPC机制的选择依据深入理解操作系统工作原理掌握底层编程技能的重要性UNIX设计哲学在现代软件开发中的应用。

AI天才研究院 1158

5w字总结 Unix系统编程学习笔记(面试向)(Unix环境高级编程/Unix环境程序设计)

文章目录一、计算C语言的数据表示与处理计算C语言的基本运算操作内存表和符号表类型转换函数类型的分析指令复合指令句法函数函数激活(Activation Record)函数激活定义函数激活存储内容二、并发多道程序设计和分时Unix分时:存储的保存和加载中断(interrupt)时钟中断( Clock Interrupt )系统调用(system call)进程切换(上下文切换)分时的实现应用层并发三、程序、进程和线程什么是程序?什么是进程?进程的状态有哪些?其转换关系是怎么样的?进程什么时候开始产生/运行?什么

weixin_47826078的博客 5057

unix高级环境编程》进程间通信——信号

这里所介绍的信号量是一种

关注校招求职,微信号:job_campus 1969

UNIX常用命令英文全称与中文解释整理

10.电子邮件与新闻组archivectlinndelmgetlistinncheckmailmailconfmailqmessagesmetamailmuttnntpgetpineslrnX WINDOWS SYSTEMreconfigstartx(start X Window)XconfiguratorXF86SetupxlsatomsxlsclientsxlsfontsList module 列表模块。3.ls:List files 列出目录下的文件。UNIX常用命令英文全称与中文解释整理。

2401_86853478的博客 147
上一篇: UNIX环境编程进程管理
下一篇: 网络编程初认识
YiHeboy
博客等级 码龄6年 48粉丝 30原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值