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

📄 signal.c

📁 minix3.1.1源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*===========================================================================* *				cause_sigalrm				     * *===========================================================================*/PRIVATE void cause_sigalrm(tp)struct timer *tp;{  int proc_nr;  register struct mproc *rmp;  proc_nr = tmr_arg(tp)->ta_int;	/* get process from timer */  rmp = &mproc[proc_nr];  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return;  if ((rmp->mp_flags & ALARM_ON) == 0) return;  rmp->mp_flags &= ~ALARM_ON;  check_sig(rmp->mp_pid, SIGALRM);}/*===========================================================================* *				do_pause				     * *===========================================================================*/PUBLIC int do_pause(){/* Perform the pause() system call. */  mp->mp_flags |= PAUSED;  return(SUSPEND);}/*===========================================================================* *				sig_proc				     * *===========================================================================*/PUBLIC void sig_proc(rmp, signo)register struct mproc *rmp;	/* pointer to the process to be signaled */int signo;			/* signal to send to process (1 to _NSIG) */{/* Send a signal to a process.  Check to see if the signal is to be caught, * ignored, tranformed into a message (for system processes) or blocked.   *  - If the signal is to be transformed into a message, request the KERNEL to * send the target process a system notification with the pending signal as an  * argument.  *  - If the signal is to be caught, request the KERNEL to push a sigcontext  * structure and a sigframe structure onto the catcher's stack.  Also, KERNEL  * will reset the program counter and stack pointer, so that when the process  * next runs, it will be executing the signal handler. When the signal handler  * returns,  sigreturn(2) will be called.  Then KERNEL will restore the signal  * context from the sigcontext structure. * If there is insufficient stack space, kill the process. */  vir_bytes new_sp;  int s;  int slot;  int sigflags;  struct sigmsg sm;  slot = (int) (rmp - mproc);  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) {	printf("PM: signal %d sent to %s process %d\n",		signo, (rmp->mp_flags & ZOMBIE) ? "zombie" : "dead", slot);	panic(__FILE__,"", NO_NUM);  }  if ((rmp->mp_flags & TRACED) && signo != SIGKILL) {	/* A traced process has special handling. */	unpause(slot);	stop_proc(rmp, signo);	/* a signal causes it to stop */	return;  }  /* Some signals are ignored by default. */  if (sigismember(&rmp->mp_ignore, signo)) {   	return;  }  if (sigismember(&rmp->mp_sigmask, signo)) {	/* Signal should be blocked. */	sigaddset(&rmp->mp_sigpending, signo);	return;  }#if ENABLE_SWAP  if (rmp->mp_flags & ONSWAP) {	/* Process is swapped out, leave signal pending. */	sigaddset(&rmp->mp_sigpending, signo);	swap_inqueue(rmp);	return;  }#endif  sigflags = rmp->mp_sigact[signo].sa_flags;  if (sigismember(&rmp->mp_catch, signo)) {	if (rmp->mp_flags & SIGSUSPENDED)		sm.sm_mask = rmp->mp_sigmask2;	else		sm.sm_mask = rmp->mp_sigmask;	sm.sm_signo = signo;	sm.sm_sighandler = (vir_bytes) rmp->mp_sigact[signo].sa_handler;	sm.sm_sigreturn = rmp->mp_sigreturn;	if ((s=get_stack_ptr(slot, &new_sp)) != OK)		panic(__FILE__,"couldn't get new stack pointer",s);	sm.sm_stkptr = new_sp;	/* Make room for the sigcontext and sigframe struct. */	new_sp -= sizeof(struct sigcontext)				 + 3 * sizeof(char *) + 2 * sizeof(int);	if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK)		goto doterminate;	rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask;	if (sigflags & SA_NODEFER)		sigdelset(&rmp->mp_sigmask, signo);	else		sigaddset(&rmp->mp_sigmask, signo);	if (sigflags & SA_RESETHAND) {		sigdelset(&rmp->mp_catch, signo);		rmp->mp_sigact[signo].sa_handler = SIG_DFL;	}	if (OK == (s=sys_sigsend(slot, &sm))) {		sigdelset(&rmp->mp_sigpending, signo);		/* If process is hanging on PAUSE, WAIT, SIGSUSPEND, tty, 		 * pipe, etc., release it.		 */		unpause(slot);		return;	}  	panic(__FILE__, "warning, sys_sigsend failed", s);  }  else if (sigismember(&rmp->mp_sig2mess, signo)) {  	if (OK != (s=sys_kill(slot,signo)))  		panic(__FILE__, "warning, sys_kill failed", s);  	return;  }doterminate:  /* Signal should not or cannot be caught.  Take default action. */  if (sigismember(&ign_sset, signo)) return;  rmp->mp_sigstatus = (char) signo;  if (sigismember(&core_sset, signo)) {#if ENABLE_SWAP	if (rmp->mp_flags & ONSWAP) {		/* Process is swapped out, leave signal pending. */		sigaddset(&rmp->mp_sigpending, signo);		swap_inqueue(rmp);		return;	}#endif	/* Switch to the user's FS environment and dump core. */	tell_fs(CHDIR, slot, FALSE, 0);	dump_core(rmp);  }  pm_exit(rmp, 0);		/* terminate process */}/*===========================================================================* *				check_sig				     * *===========================================================================*/PUBLIC int check_sig(proc_id, signo)pid_t proc_id;			/* pid of proc to sig, or 0 or -1, or -pgrp */int signo;			/* signal to send to process (0 to _NSIG) */{/* Check to see if it is possible to send a signal.  The signal may have to be * sent to a group of processes.  This routine is invoked by the KILL system * call, and also when the kernel catches a DEL or other signal. */  register struct mproc *rmp;  int count;			/* count # of signals sent */  int error_code;  if (signo < 0 || signo > _NSIG) return(EINVAL);  /* Return EINVAL for attempts to send SIGKILL to INIT alone. */  if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);  /* Search the proc table for processes to signal.  (See forkexit.c about   * pid magic.)   */  count = 0;  error_code = ESRCH;  for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {	if (!(rmp->mp_flags & IN_USE)) continue;	if ((rmp->mp_flags & ZOMBIE) && signo != 0) continue;	/* Check for selection. */	if (proc_id > 0 && proc_id != rmp->mp_pid) continue;	if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp) continue;	if (proc_id == -1 && rmp->mp_pid <= INIT_PID) continue;	if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue;	/* Check for permission. */	if (mp->mp_effuid != SUPER_USER	    && mp->mp_realuid != rmp->mp_realuid	    && mp->mp_effuid != rmp->mp_realuid	    && mp->mp_realuid != rmp->mp_effuid	    && mp->mp_effuid != rmp->mp_effuid) {		error_code = EPERM;		continue;	}	count++;	if (signo == 0) continue;	/* 'sig_proc' will handle the disposition of the signal.  The	 * signal may be caught, blocked, ignored, or cause process	 * termination, possibly with core dump.	 */	sig_proc(rmp, signo);	if (proc_id > 0) break;	/* only one process being signaled */  }  /* If the calling process has killed itself, don't reply. */  if ((mp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) return(SUSPEND);  return(count > 0 ? OK : error_code);}/*===========================================================================* *				check_pending				     * *===========================================================================*/PUBLIC void check_pending(rmp)register struct mproc *rmp;{  /* Check to see if any pending signals have been unblocked.  The   * first such signal found is delivered.   *   * If multiple pending unmasked signals are found, they will be   * delivered sequentially.   *   * There are several places in this file where the signal mask is   * changed.  At each such place, check_pending() should be called to   * check for newly unblocked signals.   */  int i;  for (i = 1; i <= _NSIG; i++) {	if (sigismember(&rmp->mp_sigpending, i) &&		!sigismember(&rmp->mp_sigmask, i)) {		sigdelset(&rmp->mp_sigpending, i);		sig_proc(rmp, i);		break;	}  }}/*===========================================================================* *				unpause					     * *===========================================================================*/PRIVATE void unpause(pro)int pro;			/* which process number */{/* A signal is to be sent to a process.  If that process is hanging on a * system call, the system call must be terminated with EINTR.  Possible * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys. * First check if the process is hanging on an PM call.  If not, tell FS, * so it can check for READs and WRITEs from pipes, ttys and the like. */  register struct mproc *rmp;  rmp = &mproc[pro];  /* Check to see if process is hanging on a PAUSE, WAIT or SIGSUSPEND call. */  if (rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED)) {	rmp->mp_flags &= ~(PAUSED | WAITING | SIGSUSPENDED);	setreply(pro, EINTR);	return;  }  /* Process is not hanging on an PM call.  Ask FS to take a look. */  tell_fs(UNPAUSE, pro, 0, 0);}/*===========================================================================* *				dump_core				     * *===========================================================================*/PRIVATE void dump_core(rmp)register struct mproc *rmp;	/* whose core is to be dumped */{/* Make a core dump on the file "core", if possible. */  int s, fd, seg, slot;  vir_bytes current_sp;  long trace_data, trace_off;  slot = (int) (rmp - mproc);  /* Can core file be written?  We are operating in the user's FS environment,   * so no special permission checks are needed.   */  if (rmp->mp_realuid != rmp->mp_effuid) return;  if ( (fd = open(core_name, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK,						CORE_MODE)) < 0) return;  rmp->mp_sigstatus |= DUMPED;  /* Make sure the stack segment is up to date.   * We don't want adjust() to fail unless current_sp is preposterous,   * but it might fail due to safety checking.  Also, we don't really want    * the adjust() for sending a signal to fail due to safety checking.     * Maybe make SAFETY_BYTES a parameter.   */  if ((s=get_stack_ptr(slot, &current_sp)) != OK)	panic(__FILE__,"couldn't get new stack pointer",s);  adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);  /* Write the memory map of all segments to begin the core file. */  if (write(fd, (char *) rmp->mp_seg, (unsigned) sizeof rmp->mp_seg)      != (unsigned) sizeof rmp->mp_seg) {	close(fd);	return;  }  /* Write out the whole kernel process table entry to get the regs. */  trace_off = 0;  while (sys_trace(T_GETUSER, slot, trace_off, &trace_data) == OK) {	if (write(fd, (char *) &trace_data, (unsigned) sizeof (long))	    != (unsigned) sizeof (long)) {		close(fd);		return;	}	trace_off += sizeof (long);  }  /* Loop through segments and write the segments themselves out. */  for (seg = 0; seg < NR_LOCAL_SEGS; seg++) {	rw_seg(1, fd, slot, seg,		(phys_bytes) rmp->mp_seg[seg].mem_len << CLICK_SHIFT);  }  close(fd);}

⌨️ 快捷键说明

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