⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signal.c

📁 minix3.1.1源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* This file handles signals, which are asynchronous events and are generally * a messy and unpleasant business.  Signals can be generated by the KILL * system call, or from the keyboard (SIGINT) or from the clock (SIGALRM). * In all cases control eventually passes to check_sig() to see which processes * can be signaled.  The actual signaling is done by sig_proc(). * * The entry points into this file are: *   do_sigaction:   perform the SIGACTION system call *   do_sigpending:  perform the SIGPENDING system call *   do_sigprocmask: perform the SIGPROCMASK system call *   do_sigreturn:   perform the SIGRETURN system call *   do_sigsuspend:  perform the SIGSUSPEND system call *   do_kill:	perform the KILL system call *   do_alarm:	perform the ALARM system call by calling set_alarm() *   set_alarm:	tell the clock task to start or stop a timer *   do_pause:	perform the PAUSE system call *   ksig_pending: the kernel notified about pending signals *   sig_proc:	interrupt or terminate a signaled process *   check_sig: check which processes to signal with sig_proc() *   check_pending:  check if a pending signal can now be delivered */#include "pm.h"#include <sys/stat.h>#include <sys/ptrace.h>#include <minix/callnr.h>#include <minix/com.h>#include <signal.h>#include <sys/sigcontext.h>#include <string.h>#include "mproc.h"#include "param.h"#define CORE_MODE	0777	/* mode to use on core image files */#define DUMPED          0200	/* bit set in status when core dumped */FORWARD _PROTOTYPE( void dump_core, (struct mproc *rmp)			);FORWARD _PROTOTYPE( void unpause, (int pro)				);FORWARD _PROTOTYPE( void handle_sig, (int proc_nr, sigset_t sig_map)	);FORWARD _PROTOTYPE( void cause_sigalrm, (struct timer *tp)		);/*===========================================================================* *				do_sigaction				     * *===========================================================================*/PUBLIC int do_sigaction(){  int r;  struct sigaction svec;  struct sigaction *svp;  if (m_in.sig_nr == SIGKILL) return(OK);  if (m_in.sig_nr < 1 || m_in.sig_nr > _NSIG) return (EINVAL);  svp = &mp->mp_sigact[m_in.sig_nr];  if ((struct sigaction *) m_in.sig_osa != (struct sigaction *) NULL) {	r = sys_datacopy(PM_PROC_NR,(vir_bytes) svp,		who, (vir_bytes) m_in.sig_osa, (phys_bytes) sizeof(svec));	if (r != OK) return(r);  }  if ((struct sigaction *) m_in.sig_nsa == (struct sigaction *) NULL)   	return(OK);  /* Read in the sigaction structure. */  r = sys_datacopy(who, (vir_bytes) m_in.sig_nsa,		PM_PROC_NR, (vir_bytes) &svec, (phys_bytes) sizeof(svec));  if (r != OK) return(r);  if (svec.sa_handler == SIG_IGN) {	sigaddset(&mp->mp_ignore, m_in.sig_nr);	sigdelset(&mp->mp_sigpending, m_in.sig_nr);	sigdelset(&mp->mp_catch, m_in.sig_nr);	sigdelset(&mp->mp_sig2mess, m_in.sig_nr);  } else if (svec.sa_handler == SIG_DFL) {	sigdelset(&mp->mp_ignore, m_in.sig_nr);	sigdelset(&mp->mp_catch, m_in.sig_nr);	sigdelset(&mp->mp_sig2mess, m_in.sig_nr);  } else if (svec.sa_handler == SIG_MESS) {	if (! (mp->mp_flags & PRIV_PROC)) return(EPERM);	sigdelset(&mp->mp_ignore, m_in.sig_nr);	sigaddset(&mp->mp_sig2mess, m_in.sig_nr);	sigdelset(&mp->mp_catch, m_in.sig_nr);  } else {	sigdelset(&mp->mp_ignore, m_in.sig_nr);	sigaddset(&mp->mp_catch, m_in.sig_nr);	sigdelset(&mp->mp_sig2mess, m_in.sig_nr);  }  mp->mp_sigact[m_in.sig_nr].sa_handler = svec.sa_handler;  sigdelset(&svec.sa_mask, SIGKILL);  mp->mp_sigact[m_in.sig_nr].sa_mask = svec.sa_mask;  mp->mp_sigact[m_in.sig_nr].sa_flags = svec.sa_flags;  mp->mp_sigreturn = (vir_bytes) m_in.sig_ret;  return(OK);}/*===========================================================================* *				do_sigpending                                * *===========================================================================*/PUBLIC int do_sigpending(){  mp->mp_reply.reply_mask = (long) mp->mp_sigpending;  return OK;}/*===========================================================================* *				do_sigprocmask                               * *===========================================================================*/PUBLIC int do_sigprocmask(){/* Note that the library interface passes the actual mask in sigmask_set, * not a pointer to the mask, in order to save a copy.  Similarly, * the old mask is placed in the return message which the library * interface copies (if requested) to the user specified address. * * The library interface must set SIG_INQUIRE if the 'act' argument * is NULL. */  int i;  mp->mp_reply.reply_mask = (long) mp->mp_sigmask;  switch (m_in.sig_how) {      case SIG_BLOCK:	sigdelset((sigset_t *)&m_in.sig_set, SIGKILL);	for (i = 1; i <= _NSIG; i++) {		if (sigismember((sigset_t *)&m_in.sig_set, i))			sigaddset(&mp->mp_sigmask, i);	}	break;      case SIG_UNBLOCK:	for (i = 1; i <= _NSIG; i++) {		if (sigismember((sigset_t *)&m_in.sig_set, i))			sigdelset(&mp->mp_sigmask, i);	}	check_pending(mp);	break;      case SIG_SETMASK:	sigdelset((sigset_t *) &m_in.sig_set, SIGKILL);	mp->mp_sigmask = (sigset_t) m_in.sig_set;	check_pending(mp);	break;      case SIG_INQUIRE:	break;      default:	return(EINVAL);	break;  }  return OK;}/*===========================================================================* *				do_sigsuspend                                * *===========================================================================*/PUBLIC int do_sigsuspend(){  mp->mp_sigmask2 = mp->mp_sigmask;	/* save the old mask */  mp->mp_sigmask = (sigset_t) m_in.sig_set;  sigdelset(&mp->mp_sigmask, SIGKILL);  mp->mp_flags |= SIGSUSPENDED;  check_pending(mp);  return(SUSPEND);}/*===========================================================================* *				do_sigreturn				     * *===========================================================================*/PUBLIC int do_sigreturn(){/* A user signal handler is done.  Restore context and check for * pending unblocked signals. */  int r;  mp->mp_sigmask = (sigset_t) m_in.sig_set;  sigdelset(&mp->mp_sigmask, SIGKILL);  r = sys_sigreturn(who, (struct sigmsg *) m_in.sig_context);  check_pending(mp);  return(r);}/*===========================================================================* *				do_kill					     * *===========================================================================*/PUBLIC int do_kill(){/* Perform the kill(pid, signo) system call. */  return check_sig(m_in.pid, m_in.sig_nr);}/*===========================================================================* *				ksig_pending				     * *===========================================================================*/PUBLIC int ksig_pending(){/* Certain signals, such as segmentation violations originate in the kernel. * When the kernel detects such signals, it notifies the PM to take further  * action. The PM requests the kernel to send messages with the process * slot and bit map for all signaled processes. The File System, for example, * uses this mechanism to signal writing on broken pipes (SIGPIPE).  * * The kernel has notified the PM about pending signals. Request pending * signals until all signals are handled. If there are no more signals, * NONE is returned in the process number field. */  int proc_nr; sigset_t sig_map; while (TRUE) {   sys_getksig(&proc_nr, &sig_map); 	/* get an arbitrary pending signal */   if (NONE == proc_nr) {		/* stop if no more pending signals */ 	break;   } else {   	handle_sig(proc_nr, sig_map);	/* handle the received signal */	sys_endksig(proc_nr);		/* tell kernel it's done */   } }  return(SUSPEND);			/* prevents sending reply */}/*===========================================================================* *				handle_sig				     * *===========================================================================*/PRIVATE void handle_sig(proc_nr, sig_map)int proc_nr;sigset_t sig_map;{  register struct mproc *rmp;  int i;  pid_t proc_id, id;  rmp = &mproc[proc_nr];  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return;  proc_id = rmp->mp_pid;  mp = &mproc[0];			/* pretend signals are from PM */  mp->mp_procgrp = rmp->mp_procgrp;	/* get process group right */  /* Check each bit in turn to see if a signal is to be sent.  Unlike   * kill(), the kernel may collect several unrelated signals for a   * process and pass them to PM in one blow.  Thus loop on the bit   * map. For SIGINT, SIGWINCH and SIGQUIT, use proc_id 0 to indicate   * a broadcast to the recipient's process group.  For SIGKILL, use   * proc_id -1 to indicate a systemwide broadcast.   */  for (i = 1; i <= _NSIG; i++) {	if (!sigismember(&sig_map, i)) continue;	switch (i) {	    case SIGINT:	    case SIGQUIT:	    case SIGWINCH:		id = 0; break;	/* broadcast to process group */	    case SIGKILL:		id = -1; break;	/* broadcast to all except INIT */	    default:		id = proc_id;		break;	}	check_sig(id, i);  }}/*===========================================================================* *				do_alarm				     * *===========================================================================*/PUBLIC int do_alarm(){/* Perform the alarm(seconds) system call. */  return(set_alarm(who, m_in.seconds));}/*===========================================================================* *				set_alarm				     * *===========================================================================*/PUBLIC int set_alarm(proc_nr, sec)int proc_nr;			/* process that wants the alarm */int sec;			/* how many seconds delay before the signal */{/* This routine is used by do_alarm() to set the alarm timer.  It is also used * to turn the timer off when a process exits with the timer still on. */  clock_t ticks;	/* number of ticks for alarm */  clock_t exptime;	/* needed for remaining time on previous alarm */  clock_t uptime;	/* current system time */  int remaining;	/* previous time left in seconds */  int s;  /* First determine remaining time of previous alarm, if set. */  if (mproc[proc_nr].mp_flags & ALARM_ON) {  	if ( (s=getuptime(&uptime)) != OK)   		panic(__FILE__,"set_alarm couldn't get uptime", s);  	exptime = *tmr_exp_time(&mproc[proc_nr].mp_timer);  	remaining = (int) ((exptime - uptime + (HZ-1))/HZ);  	if (remaining < 0) remaining = 0;	  } else {  	remaining = 0;   }  /* Tell the clock task to provide a signal message when the time comes.   *   * Large delays cause a lot of problems.  First, the alarm system call   * takes an unsigned seconds count and the library has cast it to an int.   * That probably works, but on return the library will convert "negative"   * unsigneds to errors.  Presumably no one checks for these errors, so   * force this call through.  Second, If unsigned and long have the same   * size, converting from seconds to ticks can easily overflow.  Finally,   * the kernel has similar overflow bugs adding ticks.   *   * Fixing this requires a lot of ugly casts to fit the wrong interface   * types and to avoid overflow traps.  ALRM_EXP_TIME has the right type   * (clock_t) although it is declared as long.  How can variables like   * this be declared properly without combinatorial explosion of message   * types?   */  ticks = (clock_t) (HZ * (unsigned long) (unsigned) sec);  if ( (unsigned long) ticks / HZ != (unsigned) sec)	ticks = LONG_MAX;	/* eternity (really TMR_NEVER) */  if (ticks != 0) {  	pm_set_timer(&mproc[proc_nr].mp_timer, ticks, cause_sigalrm, proc_nr);  	mproc[proc_nr].mp_flags |=  ALARM_ON;  } else if (mproc[proc_nr].mp_flags & ALARM_ON) {  	pm_cancel_timer(&mproc[proc_nr].mp_timer);  	mproc[proc_nr].mp_flags &= ~ALARM_ON;  }  return(remaining);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -