`
lobin
  • 浏览: 427242 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

C: Linux C 编程 - 信号处理

 
阅读更多

信号

 

$ kill -l

 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL

 5) SIGTRAP 6) SIGABRT 7) SIGEMT 8) SIGFPE

 9) SIGKILL10) SIGBUS11) SIGSEGV12) SIGSYS

13) SIGPIPE14) SIGALRM15) SIGTERM16) SIGURG

17) SIGSTOP18) SIGTSTP19) SIGCONT20) SIGCHLD

21) SIGTTIN22) SIGTTOU23) SIGIO24) SIGXCPU

25) SIGXFSZ26) SIGVTALRM27) SIGPROF28) SIGWINCH

 

29) SIGINFO30) SIGUSR131) SIGUSR2

 

 

写道
signal - overview of signals
https://man7.org/linux/man-pages/man7/signal.7.html

注意是signal(7),不是signal(2)。也不是linux.die.net提供的Manual。

 

/* Signals.  */
#define	SIGHUP		1	/* Hangup (POSIX).  */
#define	SIGINT		2	/* Interrupt (ANSI).  */
#define	SIGQUIT		3	/* Quit (POSIX).  */
#define	SIGILL		4	/* Illegal instruction (ANSI).  */
#define	SIGTRAP		5	/* Trace trap (POSIX).  */
#define	SIGABRT		6	/* Abort (ANSI).  */
#define	SIGIOT		6	/* IOT trap (4.2 BSD).  */
#define	SIGBUS		7	/* BUS error (4.2 BSD).  */
#define	SIGFPE		8	/* Floating-point exception (ANSI).  */
#define	SIGKILL		9	/* Kill, unblockable (POSIX).  */
#define	SIGUSR1		10	/* User-defined signal 1 (POSIX).  */
#define	SIGSEGV		11	/* Segmentation violation (ANSI).  */
#define	SIGUSR2		12	/* User-defined signal 2 (POSIX).  */
#define	SIGPIPE		13	/* Broken pipe (POSIX).  */
#define	SIGALRM		14	/* Alarm clock (POSIX).  */
#define	SIGTERM		15	/* Termination (ANSI).  */
#define	SIGSTKFLT	16	/* Stack fault.  */
#define	SIGCLD		SIGCHLD	/* Same as SIGCHLD (System V).  */
#define	SIGCHLD		17	/* Child status has changed (POSIX).  */
#define	SIGCONT		18	/* Continue (POSIX).  */
#define	SIGSTOP		19	/* Stop, unblockable (POSIX).  */
#define	SIGTSTP		20	/* Keyboard stop (POSIX).  */
#define	SIGTTIN		21	/* Background read from tty (POSIX).  */
#define	SIGTTOU		22	/* Background write to tty (POSIX).  */
#define	SIGURG		23	/* Urgent condition on socket (4.2 BSD).  */
#define	SIGXCPU		24	/* CPU limit exceeded (4.2 BSD).  */
#define	SIGXFSZ		25	/* File size limit exceeded (4.2 BSD).  */
#define	SIGVTALRM	26	/* Virtual alarm clock (4.2 BSD).  */
#define	SIGPROF		27	/* Profiling alarm clock (4.2 BSD).  */
#define	SIGWINCH	28	/* Window size change (4.3 BSD, Sun).  */
#define	SIGPOLL		SIGIO	/* Pollable event occurred (System V).  */
#define	SIGIO		29	/* I/O now possible (4.2 BSD).  */
#define	SIGPWR		30	/* Power failure restart (System V).  */
#define SIGSYS		31	/* Bad system call.  */
#define SIGUNUSED	31

#define	_NSIG		65	/* Biggest signal number + 1
				   (including real-time signals).  */

 

SIGPOLL

 

SIGIO

linux下SIGIO和SIGPOLL是同一种信号。要收到SIGIO或SIGPOLL信号,需要调用fcntl函数对相应的fd执行操作,指定F_SETOWN并指定参数为需要收到此信号的进程或进程组id。

 

这样进程还不能收到SIGIO或SIGPOLL信号,还需要调用fcntl函数对相应的fd执行操作,指定F_SETFL,将fd设置为异步模式,O_ASYNC,这样当此fd产生事件时,将会触发SIGIO或SIGPOLL信号,否则信号将被默默丢弃

 

#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>

int i;

void on_signal_io(int sig)
{
  printf("signal: num=SIGIO(%d), %d\n", sig, i++);
}

int main()
{
  int oflags;

  signal(SIGIO, on_signal_io);

  oflags = fcntl(STDIN_FILENO, F_GETFL);
  fcntl(STDIN_FILENO, F_SETFL, oflags | O_ASYNC); // O_ASYNC, FASYNC

  fcntl(STDIN_FILENO, F_SETOWN, getpid());

  while (1)
  {
    
  }

  return 0;
}

 

 

参考poll和select函数。我们完全可以通过这个信号来自己实现poll和select的事件机制。至于能否实现epoll那样的事件机制,没有去验证,估计不行,毕竟epoll这种机制是由内核实现的。像epoll的事件触发机制,首先边缘触发和水平触发就可能无法实现。

 

信号处理

sighandler_t

类型定义

typedef void (*sighandler_t)(int);

 

signal

函数原型

sighandler_t signal(int signum, sighandler_t handler);

写道
The behavior of signal() varies across UNIX versions, and has also varied historically across different versions of Linux. Avoid its use: use sigaction(2) instead. See Portability below.

signal()的行为因UNIX版本而不同,而且在历史上也因Linux的不同版本而不同。避免其使用:使用sigaction()代替。请参阅下面的可移植性。

 

sigaction

函数原型

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

 

信号堆栈上下文

signal stack context,即信号堆栈上下文

 

typedef struct {
  void  *ss_sp;     /* Base address of stack */
  int    ss_flags;  /* Flags */
  size_t ss_size;   /* Number of bytes in stack */
} stack_t;

 

sigaltstack

sigaltstack - set and/or get signal stack context

函数原型

int sigaltstack(const stack_t *ss, stack_t *oss);

 

备用信号堆栈

alternate signal stack, 即备用信号堆栈

 

用户上下文

user context,即用户上下文

 

getcontext, setcontext - get or set the user context

 

getcontext

函数原型

int getcontext(ucontext_t *ucp);

 

setcontext

函数原型

int setcontext(const ucontext_t *ucp);

 

signal

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void do_exit()
{  
  printf("exit.\n");
  exit(0);
}

void on_signal_int(int sig)
{
  printf("signal: num=SIGINT(%d)\n", sig);
  do_exit();
}

void on_signal_term(int sig)
{
  printf("signal: num=SIGTERM(%d)\n", sig);
  do_exit();
}

void on_signal_kill(int sig)
{
  printf("signal: num=SIGKILL(%d)\n", sig);
  do_exit();
}

int main(int argc, char** argv)
{
  // SIGINT signal
  signal(SIGINT, on_signal_int);
  signal(SIGTERM, on_signal_term);
  
  // The signals SIGKILL and SIGSTOP cannot be caught or ignored.
  // signal(SIGKILL, on_signal_kill);  

  while (1)
  {
    
  }

  return 0;
}

sigaction

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void do_exit()
{  
  printf("exit.\n");
  exit(0);
}

void on_signal_int_action(int signal, siginfo_t *info, void *ucontext)
{
  printf("signal: num=SIGINT(%d)\n", signal);
  do_exit();
}

void on_signal_term_action(int signal, siginfo_t *info, void *ucontext)
{
  printf("signal: num=SIGTERM(%d)\n", signal);
  do_exit();
}

void on_signal_kill_action(int signal, siginfo_t *info, void *ucontext)
{
  printf("signal: num=SIGKILL(%d)\n", signal);
  do_exit();
}

int main(int argc, char** argv)
{
  struct sigaction on_signal_int, on_signal_term/*, on_signal_kill*/;

  on_signal_int.sa_sigaction = on_signal_int_action;
  on_signal_int.sa_flags = SA_SIGINFO;

  on_signal_term.sa_sigaction = on_signal_term_action;
  on_signal_term.sa_flags = SA_SIGINFO;

  // SIGINT signal
  sigaction(SIGINT, &on_signal_int, NULL);
  // SIGTERM signal
  sigaction(SIGTERM, &on_signal_term, NULL);
  
  // The signals SIGKILL and SIGSTOP cannot be caught or ignored.
  // SIGKILL signal
  // sigaction(SIGKILL, &on_signal_kill, NULL);  

  while (1)
  {
    
  }

  return 0;
}

 

向信号处理函数传递参数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <ucontext.h>

void do_exit(int exit_code)
{  
  printf("exit.\n");
  exit(exit_code);
}

int ucstoi(stack_t stack)
{
  return *((int *) stack.ss_sp);
}

void on_signal_int_action(int signal, siginfo_t *info, void *ucontext)
{
  ucontext_t *p = (ucontext_t *) ucontext;
  int exit = ucstoi(p->uc_stack);
  printf("signal: num=SIGINT(%d), exit=%d\n", signal, exit);
  do_exit(exit);
}

void on_signal_term_action(int signal, siginfo_t *info, void *ucontext)
{
  ucontext_t *p = (ucontext_t *) ucontext;
  int exit = ucstoi(p->uc_stack);
  printf("signal: num=SIGTERM(%d), exit=%d\n", signal, exit);
  do_exit(exit);
}

void on_signal_kill_action(int signal, siginfo_t *info, void *ucontext)
{
  ucontext_t *p = (ucontext_t *) ucontext;
  int exit = ucstoi(p->uc_stack);
  printf("signal: num=SIGKILL(%d), exit=%d\n", signal, exit);
  do_exit(exit);
}

int createcontext(int arg)
{
  stack_t stack;
  ucontext_t ucontext;

  stack.ss_size = SIGSTKSZ;
  stack.ss_sp = malloc(stack.ss_size);
  stack.ss_flags = 0;

  memcpy(stack.ss_sp, &arg, sizeof(arg));

  if (sigaltstack(&stack, NULL) == -1)
  {
    printf("sig alt stack err.\n");
    return 1;
  }

  ucontext.uc_link = NULL;
  ucontext.uc_stack = stack;
  if (getcontext(&ucontext) == -1) 
  {
    printf("get context err.\n");
    return 1;
  }
  return 0;
}

int main(int argc, char** argv)
{
  struct sigaction on_signal_int, on_signal_term/*, on_signal_kill*/;

  on_signal_int.sa_sigaction = on_signal_int_action;
  on_signal_int.sa_flags = SA_SIGINFO;

  on_signal_term.sa_sigaction = on_signal_term_action;
  on_signal_term.sa_flags = SA_SIGINFO;

  int i = -1;
  if (argc == 2) 
  {
    i = atoi(argv[1]);
  }
  if (createcontext(i))
  {
    printf("create context err.\n");
    return 1;
  }

  // SIGINT signal
  sigaction(SIGINT, &on_signal_int, NULL);
  // SIGTERM signal
  sigaction(SIGTERM, &on_signal_term, NULL);
  
  // The signals SIGKILL and SIGSTOP cannot be caught or ignored.
  // SIGKILL signal
  // sigaction(SIGKILL, &on_signal_kill, NULL);  

  while (1)
  {
    
  }

  return 0;
}

 

 

0
0
分享到:
评论

相关推荐

    Linux下C语言编程--信号处理函数.

    ### Linux下C语言编程——信号处理函数 #### 一、信号的基本概念与产生 在Linux系统中,**信号**是一种轻量级的进程间通信机制,用于通知接收进程某个特定事件的发生。它不仅可以由硬件异常(如除零错误)触发,也...

    01--Linux系统编程-信号.docx

    在编写Linux系统编程时,理解并正确处理信号是非常重要的。程序员可以通过signal()、sigaction()等系统调用来注册信号处理器,定义信号发生时的行为,如执行默认操作、忽略信号或调用自定义的处理函数。正确地管理和...

    Linux下C语言应用编程(作者-杨铸)配套教学ppt

    这组资源,"Linux下C语言应用编程(作者-杨铸)配套教学ppt",提供了对Linux环境下C语言编程的深入理解和实践指导。以下是一些核心知识点的详细说明: 1. **Linux下C语言编程环境**: - `11-Linux下C语言编程环境....

    Linux下C语言应用编程-作者-杨铸-配套ppt-源代码-教学大纲

    源代码文件“linuxc.tgz”是一个压缩包,其中包含了书中各个主题的实例代码。学生可以参考这些代码来加深理解,同时通过实际操作来锻炼编程技能。源代码涵盖了上述所有PPT讲解的主题,如简单的文件操作示例、多进程...

    Linux下C语言编程--进程通信、消息管理

    本文将详细介绍Linux环境下C语言编程中的几种进程通信方法,包括POSIX无名信号量、System V信号量、System V消息队列以及System V共享内存。 #### 1. POSIX无名信号量 ##### 理论基础 信号量是一种用于控制多个...

    Linux下C语言编程--时间概念

    在Linux环境下进行C语言编程时,时间概念是一个重要的部分,涉及到如何获取、处理和测量时间。以下是对这些知识点的详细说明: 1. **时间表示**: 在C语言中,时间通常通过`time_t`类型表示,它是一个整型变量,...

    Linux下C语言编程--线程操作

    ### Linux下C语言编程——线程操作 #### 前言:Linux下线程的创建与基础使用 在Linux环境中,线程作为一种重要的并发机制,为开发者提供了在单个进程中执行多个任务的能力。相较于进程,线程之间的切换成本更低,...

    Linux下C语言编程——信号处理

    ### Linux下C语言编程——信号处理 #### 一、引言 在Linux环境下,C语言是一种非常重要的开发工具,尤其在系统级编程方面。信号处理是C语言编程中不可或缺的一部分,它涉及到进程间的通信机制以及如何让程序能够...

    linux-c.zip_C语言_Linux C语言_linux_linux-c

    在Linux环境下进行C语言编程是许多开发者和技术爱好者深入操作系统内核、实现系统级程序或高效应用的重要途径。本文将详细探讨“Linux下C语言”这一主题,基于标题和描述提供的信息,我们将涵盖C语言的基本概念、...

    Linux下C语言应用编程--随书源代码

    5. **信号处理**:信号是Linux系统中进程间通信的一种方式,通过signal、raise、sigaction等函数可以捕获和处理信号,实现特定的行为。 6. **系统调用**:Linux提供了丰富的系统调用,如open、close、read、write等...

    linux操作系统下c语言编程入门

    ### Linux操作系统下C语言编程入门知识点详解 #### 一、目录介绍 本文档旨在为初次接触Linux环境下C语言编程的学习者提供全面的指导。主要内容包括Linux下的C语言基础知识、进程管理、文件操作、时间处理、信号...

    c语言linux系统编程入门

    ### C语言Linux系统编程入门知识点概述 #### 一、Linux下的C语言编程基础 ##### 1. 源程序的编译 - **GCC编译器**: 在Linux环境下,使用GCC(GNU Compiler Collection)作为主要的编译工具。GCC不仅支持C语言,还...

    linux系统编程_linux系统编程-中文_

    在文件I/O方面,Linux系统编程涉及文件描述符、标准输入/输出流、文件打开和关闭、读写操作以及错误处理。文件系统是另一个重要概念,如挂载、卸载、目录操作和文件权限管理等。此外,还要掌握套接字编程,这是网络...

Global site tag (gtag.js) - Google Analytics