linux系统编程之信号(二) 信号发送函数及不同精度的睡眠

一、kill, raise, killpg 函数

int kill(pid_t pid, int sig);

int raise(int sig);

int killpg(int pgrp, int sig);

kill命令是调用kill函数实现的,kill函数可以给一个指定的进程或进程组发送指定的信号,其中kill 函数的pid 参数取值不同表示不同含义,具体可man 一下。raise函数可以给当前进程发送指定的信号(自己给自己发信号)。killpg 函数可以给进程组发生信号。这三个函数都是成功返回0,错误返回-1。下面是个小程序示例:

/*************************************************************************    > File Name: process_.c    > Author: Simba    > Mail: dameng34@163.com    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST ************************************************************************/#include<sys/types.h>#include<sys/stat.h>#include<unistd.h>#include<fcntl.h>#include<stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#include<signal.h>#define ERR_EXIT(m) \    do { \        perror(m); \        exit(EXIT_FAILURE); \    } while(0)void handler(int sig);int main(int argc, char *argv[]){    if (signal(SIGUSR1, handler) == SIG_ERR)        ERR_EXIT("signal error");    pid_t pid = fork();    if (pid == -1)        ERR_EXIT("fork error");    if (pid == 0)    {        /*            pid = getpgrp(); // 得到进程组pid            kill(-pid, SIGUSR1); //向进程组发送信号        */        killpg(getpgrp(), SIGUSR1);        exit(EXIT_SUCCESS); // 子进程处理完信号才退出    }    int n = 5;    do    {        n = sleep(n); // sleep会被信号打断,返回unslept的时间    }    while (n > 0);    return 0;}void handler(int sig){    printf("recv a sig=%d\n", sig);}/* raise(sig) 等价于 kill(getpid(), sig) 给自己发送信号 */

程序中注册信号在fork之前,故子进程也会继承,在子进程中对进程组发送了信号,故信号处理函数会被调用两次:

simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./kill

recv a sig=10

recv a sig=10

simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$

因为sleep 函数会被信号处理函数打断(RETURN VALUE: Zero if the requested time has elapsed, or the number of seconds left to sleep, if the call was interrupted  by  a signal handler.),如果我们想让其睡够5s, 则可以用一个while循环判断其返回值。这里需要注意的是输出两次recv之后继续睡眠的时间是不一定的,也有可能是5s,即信号处理函数在调用sleep之前已经被调用(子进程先被系统调度执行),sleep未被中断。也表明一点:只要接收到信号,信号处理函数可以在任意某个时刻被调用,不仅仅只在进程主动调用sleep, pause等函数(让cpu去调度运行其他程序)的时候,cpu一直都在进行进程的调度,进行用户空间和内核空间的切换, 当某个时刻要从内核返回到该进程的用户空间代码继续执行之前,首先就会处理PCB中记录的信号。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, 函数
, include
, 进程
, 信号处理
, 信号
, sleep函数
编译APUE
高精度可编程直流电源、高精度时基信号发生器、可编程信号发生器、linux信号编程、linux信号量编程,以便于您获取更多的相关知识。

时间: 2024-07-30 15:03:49

linux系统编程之信号(二) 信号发送函数及不同精度的睡眠的相关文章

linux系统编程基础(二) C 标准IO 库函数与Unbuffered IO函数

先来看看C标准I/O库函数是如何用系统调用实现的. fopen(3) 调用open(2)打开指定的文件,返回一个文件描述符(就是一个int 类型的编号),分配一个FILE 结构体,其中包含该文件的描述符.I/O缓冲区和当前读写位置等信息,返回这个FILE 结构体的地址. fgetc(3) 通过传入的FILE *参数找到该文件的描述符.I/O缓冲区和当前读写位置,判断能否从I/O缓冲 区中读到下一个字符,如果能读到就直接返回该字符,否则调用read(2),把文件描述符传进 去,让内核读取该文件的数

《Linux系统编程(第2版)》——1.4 Linux编程的概念

1.4 Linux编程的概念 本节给出了Linux系统提供的服务的简要概述.所有的UNIX系统,包括Linux,提供了共同的抽象和接口集合.实际上,UNIX本身就是由这些共性定义的,比如对文件和进程的抽象.管道和socket的管理接口等等,都构成了UNIX系统的核心. 本概述假定你对Linux环境很熟悉:会使用shell的基础命令.能够编译简单的C程序.它不是关于Linux或其编程环境的,而是关于Linux系统编程的基础. 1.4.1 文件和文件系统文件是Linux系统中最基础最重要的抽象.Li

《Linux系统编程(第2版)》——第1章 入门和基本概念 1.1 系统编程

第1章 入门和基本概念 摆在你面前的是一本关于系统编程的书,你将在本书中学习到编写系统软件的相关技术和技巧.系统软件运行在系统的底层,与内核和系统核心库进行交互.常见的系统软件包括Shell.文本编辑器.编译器.调试器.核心工具(GNU Core Utilities)以及系统守护进程.此外,网络服务.Web服务和数据库也属于系统软件的范畴.这些程序都是基于内核和C库实现的,可以称为"纯"系统软件.相对地,其他软件(如高级GUI应用),很少和底层直接交互.有些程序员一直在编写系统软件,而

《Linux系统编程(第2版)》——导读

前言 这本书是关于Linux上的系统编程."系统编程"是指编写系统软件,其代码在底层运行,直接跟内核和核心系统库对话.换句话说,本书的主题是Linux系统调用和底层函数说明,如C库定义的函数. 虽然已经有很多书探讨UNIX上的系统编程,却很少有专注于探讨Linux方面的书籍,而探讨最新版本的Linux以及Linux特有的高级接口的书籍更是凤毛麟角.此外,本书还有一个优势:我为Linux贡献了很多代码,包括内核及其上面的系统软件.实际上,本书中提到的一些系统调用和系统软件就是我实现的.因

LINUX系统编程 LINUX 虚拟内存

LINUX 虚拟内存 以32位操作系统为例子,因为64位系统虚拟地址过大为2^64,32位仅仅为2^32=4G更利于描述,但是原理东西都一样 这首先要从程序和进程之间的关系开始,我们一般写好一段C\C++代码编译后仅仅为可执行文件假设为a.out,我们 运行a.out的时候,这个才叫进程,进程是OS级别抽象的实体(PCB task_struct结构体),为程序运行进行各种检查和 系统资源分配,一个PCB包含部分信息如下: (摘至刑文鹏LINUX系统编程讲义) * 进程id.系统中每个进程有唯一的

《Linux系统编程(第2版)》——1.2 API和ABI

1.2 API和ABI 程序员都希望自己实现的程序能够一直运行在其声明支持的所有系统上.他们希望能在自己的Linux版本上运行的程序也能够运行于其他Linux版本,同时还可以运行在其他支持Linux体系结构的更新(或更老)的Linux版本上. 在系统层,有两组独立的影响可移植性的定义和描述.一是应用程序编程接口(Application Programming Interface,API),二是应用程序二进制接口(Application Binary Interface,ABI),它们都是用来定义

linux系统编程之文件与I/O(六) fcntl函数与文件锁

一.fcntl函数 功能:操纵文件描述符,改变已打开的文件的属性 int fcntl(int fd, int cmd, ... /* arg */ ); cmd的取值可以如下: 复制文件描述符 F_DUPFD (long) 设置/获取文件描述符标志 F_GETFD (void) F_SETFD (long) 设置/获取文件状态标志 F_GETFL (void) F_SETFL (long) 获取/设置文件锁 F_GETLK F_SETLK,F_SETLKW 其中复制文件描述符可参见<linux系

《Linux系统编程(第2版)》——2.12 结束语

2.12 结束语 本章讨论了Linux系统编程的基础:文件I/O.在Linux这样遵循一切皆文件的操作系统中,了解如何打开.读.写和关闭文件是非常重要的.所有这些操作都是传统的UNIX方式,很多标准都涵盖它们.

《Linux系统编程(第2版)》——1.5 开始系统编程

1.5 开始系统编程 这一章着眼于Linux系统编程的基础概念并从程序员视角探索Linux系统.下一章将讨论基本的文件I/O,这当然包括读写文件,但是由于Linux把很多接口以文件形式实现,因此文件I/O的至关重要性不仅仅是对于文件而言,对于Linux系统的很多其他方面亦是如此. 了解了这些基础知识后,可以开始深入探索真正的系统编程了.我们一起动手吧.