day

xiaoxiao2021-02-28  101

一信号的处理 1 发送信号的系统函数 1raise sleepusleeppause 2alarm 2 信号集的基本概念和基本操作 1基本概念2基本操作 sigemptyset - 清空信号集sigfillset - 填满信号集sigaddset - 添加信号到信号集中sigdelset - 删除信号集中的信号sigismember - 判断信号是否存在 3 信号的屏蔽 1sigprocmask2sigpending 4 计时器5 扩展 1sigaction2sigqueue 二进程间的通信技术 1 基本概念2 通信方式

一、信号的处理

1.1 发送信号的系统函数

(1)raise()

#include <signal.h> int raise(int sig); 功能: 主要用于给当前正在调用的线程/线程发送参数指定的信号,对于单线程的程序来说,等价于 kill(getpid(), sig); 返回值: success —- 0,error —- 非0;
sleep()
#include <unistd.h> unsigned int sleep(unsigned int seconds); 功能: 主要用于使得当前正在调用的线程进入睡眠状态,直到参数指定的秒数睡够了,或者一个不能被忽略的信号到达了; 返回值: 如果参数指定的秒数过去了,则返回0,否则返回还没有来得及睡的秒数,也就是剩余的秒数;
usleep()
#include <unistd.h> int usleep(useconds_t usec); //useconds = unsigned int; 功能: 主要用于使得当前正在调用的线程睡眠参数指定的微秒;
pause()
#include <unistd.h> int pause(void); 功能: 主要用于是的当前正在调用的进程或线程暂停程序的执行,等待信号的到来; 返回值: 只有当信号被捕获时返回-1,并设置errno为EINTR;

(2)alarm()

#include <unistd.h> unsigned int alarm(unsigned int seconds);

功能:   主要用于在进过参数指定的秒数之后,给当前正在调用的进程发送SIGALRM信号;   每次重新设置闹钟之后都会取消之前的闹钟,当参数为0时,专门用于取消闹钟;

返回值:   如果之前没有闹钟则返回0,否则返回之前闹钟剩余的秒数;


1.2 信号集的基本概念和基本操作

(1)基本概念

  信号集本质上就是若干个信号组成的集合。

思考:   请问采用最节省内存空间的方式设计信号集的数据类型,如何设计?

分析:   int arr[64];   => 4*64 = 256B   short arr[64];   => 2*64 = 128B   char arr[64];   => 1*64 = 64B 采用每一个二进制位来代表一个信号,使用1表示有该信号,使用0表示没有该信号;=> 8B   … 0010 0011   => 存在信号1、信号2、信号6

结论:   操作系统内部使用数据类型:sigset_t表示信号集的数据类型,该数据类型的大小是:128B;

typedef struct { unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))]; } __sigset_t; typedef __sigset_t sigset_t

(2)基本操作

sigemptyset() - 清空信号集
#include <signal.h> int sigemptyset(sigset_t *set);
sigfillset() - 填满信号集
#include <signal.h> int sigfillset(sigset_t *set);
sigaddset() - 添加信号到信号集中
#include <signal.h> int sigaddset(sigset_t *set, int signum);
sigdelset() - 删除信号集中的信号
#include <signal.h> int sigdelset(sigset_t *set, int signum);
sigismember() - 判断信号是否存在
#include <signal.h> int sigismember(const sigset_t *set, int signum);

返回值:   信号存在返回1,信号不存在返回0,出错返回-1;


1.3 信号的屏蔽

  在某些特殊程序的执行过程中,可能不允许被信号打断,此时就需要使用信号的屏蔽技术来解决该问题;

(1)sigprocmask()

#include <signal.h> /* Prototype for the glibc wrapper function */ int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); 功能: 主要用于检查 / 修改即将屏蔽的信号集; 参数: 第一个参数:具体的屏蔽方式;   SIG_BLOCK - 使用当前屏蔽集 + 参数set屏蔽集         - ABC + CDE(set) =>ABCDE   SIG_UNBLOCK - 使用当前屏蔽集 - 参数set屏蔽集         - ABC - CDE(set) => AB   SIG_SETMASK - 使用参数set屏蔽集替换当前屏蔽集         - ABC CDE(set) => CDE 第二个参数:信号集类型的指针,用于指定新的信号集; 第三个参数:信号集类型的指针,用于带出之前屏蔽的信号集;       如果不想带出之前的屏蔽集,该参数给NULL即可;

注意:   信号的屏蔽并不是删除信号,而是相当于用一个隔板把信号档起来,对于可靠信号来说,产生了多少次,则在隔板的另一侧会排队等待多少个,而对于不可靠信号来说,无论产生了多少次,在隔板的另一侧只有一个信号排队等待,当信号的屏蔽解除时,相当于将隔板移开,只要进程不结束,则全部依次处理;

(2)sigpending()

#include <signal.h> int sigpending(sigset_t *set); 功能: 主要用于获取信号屏蔽期间来过但没来得及处理的信号集,通过参数set返回;

1.4 计时器

  在linux系统中,操作系统会为每一个进程管理3种计时器,分别为:真实计时器、虚拟计时器以及实用计时器,一般都使用真实计时器进行计时;

#include <sys/time.h> int getitimer(int which, struct itimerval *curr_value); int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value); 功能: 主要用于获取 / 设置计时器的参数信息; 参数: 第一个参数:计时器的类型;   ITIMER_REAL - 真实计时器,产生SIGALRM信号          - 统计进程消耗的真实时间   ITIMER_VIRTUAL - 虚拟计时器,产生SIGVTALRM信号           - 统计进程在用户态下消耗的时间(了解)   ITIMER_PROF - 实用计时器,产生SIGPROF信号          - 统计进程在用户态和内核态消耗的总时间 第二个参数:结构体指针,用于指定计时器的新值; struct itimerval { struct timeval it_interval; /* 间隔时间 */ struct timeval it_value; /* 开始时间 */ }; struct timeval { time_t tv_sec; /* 秒 */ suseconds_t tv_usec; /* 微秒 */ };

   第三个参数:结构体指针,用于带出设置之前的旧值;


1.5 扩展

(1)sigaction()

#include <signal.h> int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 功能: 主要用于设置信号的处理方式,signal()的增强版; 参数: 第一个参数:具体的信号值 / 信号名称;(SIGKILL和SIGSTOP除外) 第二个参数:结构体指针,设置指定信号新的处理方式; struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); }; struct siginfo_t { int si_signo; /* 信号值 */ ... }

   第三个参数:结构体指针,获取指定信号原来的处理方式;

(2)sigqueue()

#include <signal.h> int sigqueue(pid_t pid, int sig, const union sigval value); 功能: 主要用于向指定的进程发送指定的信号,还可以带一个附加数据; 参数: 第一个参数:指定进程的进程号; 第二个参数:具体的信号值 / 信号名称,类似kill();   0 - - - - - 测试指定的进程是否存在 第三个参数:联合类型, union sigval { int sival_int; void *sival_ptr; };

… …

二、进程间的通信技术

2.1 基本概念

  两个 / 多个进程之间的信息交互,就叫做进程间的通信;

2.2 通信方式

文件信号管道共享内存消息队列(重点)信号量集网络(重点) … …

其中4、5、6通信方式统称为XSI IPC通信方式(X/open System Interface Inter-Process Communication)

练习:   尝试查询sigaction()的用法;

明日预报: (1)进程间的通信技术;
转载请注明原文地址: https://www.6miu.com/read-96253.html

最新回复(0)