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

📄 signal.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
}inline intkill_proc_info(int sig, struct siginfo *info, pid_t pid){	int error;	struct task_struct *p;	read_lock(&tasklist_lock);	p = find_task_by_pid(pid);	error = -ESRCH;	if (p)		error = send_sig_info(sig, info, p);	read_unlock(&tasklist_lock);	return error;}/* * kill_something_info() interprets pid in interesting ways just like kill(2). * * POSIX specifies that kill(-1,sig) is unspecified, but what we have * is probably wrong.  Should make it like BSD or SYSV. */static int kill_something_info(int sig, struct siginfo *info, int pid){	if (!pid) {		return kill_pg_info(sig, info, current->pgrp);	} else if (pid == -1) {		int retval = 0, count = 0;		struct task_struct * p;		read_lock(&tasklist_lock);		for_each_task(p) {			if (p->pid > 1 && p != current) {				int err = send_sig_info(sig, info, p);				++count;				if (err != -EPERM)					retval = err;			}		}		read_unlock(&tasklist_lock);		return count ? retval : -ESRCH;	} else if (pid < 0) {		return kill_pg_info(sig, info, -pid);	} else {		return kill_proc_info(sig, info, pid);	}}/* * These are for backward compatibility with the rest of the kernel source. */intsend_sig(int sig, struct task_struct *p, int priv){	return send_sig_info(sig, (void*)(long)(priv != 0), p);}voidforce_sig(int sig, struct task_struct *p){	force_sig_info(sig, (void*)1L, p);}intkill_pg(pid_t pgrp, int sig, int priv){	return kill_pg_info(sig, (void *)(long)(priv != 0), pgrp);}intkill_sl(pid_t sess, int sig, int priv){	return kill_sl_info(sig, (void *)(long)(priv != 0), sess);}intkill_proc(pid_t pid, int sig, int priv){	return kill_proc_info(sig, (void *)(long)(priv != 0), pid);}/* * Joy. Or not. Pthread wants us to wake up every thread * in our parent group. */static void wake_up_parent(struct task_struct *parent){	struct task_struct *tsk = parent;	do {		wake_up_interruptible(&tsk->wait_chldexit);		tsk = next_thread(tsk);	} while (tsk != parent);}/* * Let a parent know about a status change of a child. */void do_notify_parent(struct task_struct *tsk, int sig){	struct siginfo info;	int why, status;	info.si_signo = sig;	info.si_errno = 0;	info.si_pid = tsk->pid;	info.si_uid = tsk->uid;	/* FIXME: find out whether or not this is supposed to be c*time. */	info.si_utime = hz_to_std(tsk->times.tms_utime);	info.si_stime = hz_to_std(tsk->times.tms_stime);	status = tsk->exit_code & 0x7f;	why = SI_KERNEL;	/* shouldn't happen */	switch (tsk->state) {	case TASK_STOPPED:		/* FIXME -- can we deduce CLD_TRAPPED or CLD_CONTINUED? */		if (tsk->ptrace & PT_PTRACED)			why = CLD_TRAPPED;		else			why = CLD_STOPPED;		break;	default:		if (tsk->exit_code & 0x80)			why = CLD_DUMPED;		else if (tsk->exit_code & 0x7f)			why = CLD_KILLED;		else {			why = CLD_EXITED;			status = tsk->exit_code >> 8;		}		break;	}	info.si_code = why;	info.si_status = status;	send_sig_info(sig, &info, tsk->p_pptr);	wake_up_parent(tsk->p_pptr);}/* * We need the tasklist lock because it's the only * thing that protects out "parent" pointer. * * exit.c calls "do_notify_parent()" directly, because * it already has the tasklist lock. */voidnotify_parent(struct task_struct *tsk, int sig){	read_lock(&tasklist_lock);	do_notify_parent(tsk, sig);	read_unlock(&tasklist_lock);}EXPORT_SYMBOL(dequeue_signal);EXPORT_SYMBOL(flush_signals);EXPORT_SYMBOL(force_sig);EXPORT_SYMBOL(force_sig_info);EXPORT_SYMBOL(kill_pg);EXPORT_SYMBOL(kill_pg_info);EXPORT_SYMBOL(kill_proc);EXPORT_SYMBOL(kill_proc_info);EXPORT_SYMBOL(kill_sl);EXPORT_SYMBOL(kill_sl_info);EXPORT_SYMBOL(notify_parent);EXPORT_SYMBOL(recalc_sigpending);EXPORT_SYMBOL(send_sig);EXPORT_SYMBOL(send_sig_info);EXPORT_SYMBOL(block_all_signals);EXPORT_SYMBOL(unblock_all_signals);/* * System call entry points. *//* * We don't need to get the kernel lock - this is all local to this * particular thread.. (and that's good, because this is _heavily_ * used by various programs) */asmlinkage longsys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize){	int error = -EINVAL;	sigset_t old_set, new_set;	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (sigsetsize != sizeof(sigset_t))		goto out;	if (set) {		error = -EFAULT;		if (copy_from_user(&new_set, set, sizeof(*set)))			goto out;		sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));		spin_lock_irq(&current->sigmask_lock);		old_set = current->blocked;		error = 0;		switch (how) {		default:			error = -EINVAL;			break;		case SIG_BLOCK:			sigorsets(&new_set, &old_set, &new_set);			break;		case SIG_UNBLOCK:			signandsets(&new_set, &old_set, &new_set);			break;		case SIG_SETMASK:			break;		}		current->blocked = new_set;		recalc_sigpending(current);		spin_unlock_irq(&current->sigmask_lock);		if (error)			goto out;		if (oset)			goto set_old;	} else if (oset) {		spin_lock_irq(&current->sigmask_lock);		old_set = current->blocked;		spin_unlock_irq(&current->sigmask_lock);	set_old:		error = -EFAULT;		if (copy_to_user(oset, &old_set, sizeof(*oset)))			goto out;	}	error = 0;out:	return error;}long do_sigpending(void *set, unsigned long sigsetsize){	long error = -EINVAL;	sigset_t pending;	if (sigsetsize > sizeof(sigset_t))		goto out;	spin_lock_irq(&current->sigmask_lock);	sigandsets(&pending, &current->blocked, &current->pending.signal);	spin_unlock_irq(&current->sigmask_lock);	error = -EFAULT;	if (!copy_to_user(set, &pending, sigsetsize))		error = 0;out:	return error;}	asmlinkage longsys_rt_sigpending(sigset_t *set, size_t sigsetsize){	return do_sigpending(set, sigsetsize);}asmlinkage longsys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,		    const struct timespec *uts, size_t sigsetsize){	int ret, sig;	sigset_t these;	struct timespec ts;	siginfo_t info;	long timeout = 0;	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (sigsetsize != sizeof(sigset_t))		return -EINVAL;	if (copy_from_user(&these, uthese, sizeof(these)))		return -EFAULT;			/*	 * Invert the set of allowed signals to get those we	 * want to block.	 */	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));	signotset(&these);	if (uts) {		if (copy_from_user(&ts, uts, sizeof(ts)))			return -EFAULT;		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0		    || ts.tv_sec < 0)			return -EINVAL;	}	spin_lock_irq(&current->sigmask_lock);	sig = dequeue_signal(&these, &info);	if (!sig) {		timeout = MAX_SCHEDULE_TIMEOUT;		if (uts)			timeout = (timespec_to_jiffies(&ts)				   + (ts.tv_sec || ts.tv_nsec));		if (timeout) {			/* None ready -- temporarily unblock those we're			 * interested while we are sleeping in so that we'll			 * be awakened when they arrive.  */			sigset_t oldblocked = current->blocked;			sigandsets(&current->blocked, &current->blocked, &these);			recalc_sigpending(current);			spin_unlock_irq(&current->sigmask_lock);			current->state = TASK_INTERRUPTIBLE;			timeout = schedule_timeout(timeout);			spin_lock_irq(&current->sigmask_lock);			sig = dequeue_signal(&these, &info);			current->blocked = oldblocked;			recalc_sigpending(current);		}	}	spin_unlock_irq(&current->sigmask_lock);	if (sig) {		ret = sig;		if (uinfo) {			if (copy_siginfo_to_user(uinfo, &info))				ret = -EFAULT;		}	} else {		ret = -EAGAIN;		if (timeout)			ret = -EINTR;	}	return ret;}asmlinkage longsys_kill(int pid, int sig){	struct siginfo info;	info.si_signo = sig;	info.si_errno = 0;	info.si_code = SI_USER;	info.si_pid = current->pid;	info.si_uid = current->uid;	return kill_something_info(sig, &info, pid);}asmlinkage longsys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo){	siginfo_t info;	if (copy_from_user(&info, uinfo, sizeof(siginfo_t)))		return -EFAULT;	/* Not even root can pretend to send signals from the kernel.	   Nor can they impersonate a kill(), which adds source info.  */	if (info.si_code >= 0)		return -EPERM;	info.si_signo = sig;	/* POSIX.1b doesn't mention process groups.  */	return kill_proc_info(sig, &info, pid);}intdo_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact){	struct k_sigaction *k;	if (sig < 1 || sig > _NSIG ||	    (act && (sig == SIGKILL || sig == SIGSTOP)))		return -EINVAL;	k = &current->sig->action[sig-1];	spin_lock(&current->sig->siglock);	if (oact)		*oact = *k;	if (act) {		*k = *act;		sigdelsetmask(&k->sa.sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP));		/*		 * POSIX 3.3.1.3:		 *  "Setting a signal action to SIG_IGN for a signal that is		 *   pending shall cause the pending signal to be discarded,		 *   whether or not it is blocked."		 *		 *  "Setting a signal action to SIG_DFL for a signal that is		 *   pending and whose default action is to ignore the signal		 *   (for example, SIGCHLD), shall cause the pending signal to		 *   be discarded, whether or not it is blocked"		 *		 * Note the silly behaviour of SIGCHLD: SIG_IGN means that the		 * signal isn't actually ignored, but does automatic child		 * reaping, while SIG_DFL is explicitly said by POSIX to force		 * the signal to be ignored.		 */		if (k->sa.sa_handler == SIG_IGN		    || (k->sa.sa_handler == SIG_DFL			&& (sig == SIGCONT ||			    sig == SIGCHLD ||			    sig == SIGWINCH))) {			spin_lock_irq(&current->sigmask_lock);			if (rm_sig_from_queue(sig, current))				recalc_sigpending(current);			spin_unlock_irq(&current->sigmask_lock);		}	}	spin_unlock(&current->sig->siglock);	return 0;}int do_sigaltstack (const stack_t *uss, stack_t *uoss, unsigned long sp){	stack_t oss;	int error;	if (uoss) {		oss.ss_sp = (void *) current->sas_ss_sp;		oss.ss_size = current->sas_ss_size;		oss.ss_flags = sas_ss_flags(sp);	}	if (uss) {		void *ss_sp;		size_t ss_size;		int ss_flags;		error = -EFAULT;		if (verify_area(VERIFY_READ, uss, sizeof(*uss))		    || __get_user(ss_sp, &uss->ss_sp)		    || __get_user(ss_flags, &uss->ss_flags)		    || __get_user(ss_size, &uss->ss_size))			goto out;		error = -EPERM;		if (on_sig_stack (sp))			goto out;		error = -EINVAL;		/*		 *		 * Note - this code used to test ss_flags incorrectly		 *  	  old code may have been written using ss_flags==0		 *	  to mean ss_flags==SS_ONSTACK (as this was the only		 *	  way that worked) - this fix preserves that older		 *	  mechanism		 */		if (ss_flags != SS_DISABLE && ss_flags != SS_ONSTACK && ss_flags != 0)			goto out;		if (ss_flags == SS_DISABLE) {			ss_size = 0;			ss_sp = NULL;		} else {			error = -ENOMEM;			if (ss_size < MINSIGSTKSZ)				goto out;		}		current->sas_ss_sp = (unsigned long) ss_sp;		current->sas_ss_size = ss_size;	}	if (uoss) {		error = -EFAULT;		if (copy_to_user(uoss, &oss, sizeof(oss)))			goto out;	}	error = 0;out:	return error;}asmlinkage longsys_sigpending(old_sigset_t *set){	return do_sigpending(set, sizeof(*set));}#if !defined(__alpha__)/* Alpha has its own versions with special arguments.  */asmlinkage longsys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset){	int error;	old_sigset_t old_set, new_set;	if (set) {		error = -EFAULT;		if (copy_from_user(&new_set, set, sizeof(*set)))			goto out;		new_set &= ~(sigmask(SIGKILL)|sigmask(SIGSTOP));		spin_lock_irq(&current->sigmask_lock);		old_set = current->blocked.sig[0];		error = 0;		switch (how) {		default:			error = -EINVAL;			break;		case SIG_BLOCK:			sigaddsetmask(&current->blocked, new_set);			break;		case SIG_UNBLOCK:			sigdelsetmask(&current->blocked, new_set);			break;		case SIG_SETMASK:			current->blocked.sig[0] = new_set;			break;		}		recalc_sigpending(current);		spin_unlock_irq(&current->sigmask_lock);		if (error)			goto out;		if (oset)			goto set_old;	} else if (oset) {		old_set = current->blocked.sig[0];	set_old:		error = -EFAULT;		if (copy_to_user(oset, &old_set, sizeof(*oset)))			goto out;	}	error = 0;out:	return error;}#ifndef __sparc__asmlinkage longsys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact,		 size_t sigsetsize){	struct k_sigaction new_sa, old_sa;	int ret = -EINVAL;	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (sigsetsize != sizeof(sigset_t))		goto out;	if (act) {		if (copy_from_user(&new_sa.sa, act, sizeof(new_sa.sa)))			return -EFAULT;	}	ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);	if (!ret && oact) {		if (copy_to_user(oact, &old_sa.sa, sizeof(old_sa.sa)))			return -EFAULT;	}out:	return ret;}#endif /* __sparc__ */#endif#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)/* * For backwards compatibility.  Functionality superseded by sigprocmask. */asmlinkage longsys_sgetmask(void){	/* SMP safe */	return current->blocked.sig[0];}asmlinkage longsys_ssetmask(int newmask){	int old;	spin_lock_irq(&current->sigmask_lock);	old = current->blocked.sig[0];	siginitset(&current->blocked, newmask & ~(sigmask(SIGKILL)|						  sigmask(SIGSTOP)));	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	return old;}#endif /* !defined(__alpha__) */#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && \    !defined(__arm__)/* * For backwards compatibility.  Functionality superseded by sigaction. */asmlinkage unsigned longsys_signal(int sig, __sighandler_t handler){	struct k_sigaction new_sa, old_sa;	int ret;	new_sa.sa.sa_handler = handler;	new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;	ret = do_sigaction(sig, &new_sa, &old_sa);	return ret ? ret : (unsigned long)old_sa.sa.sa_handler;}#endif /* !alpha && !__ia64__ && !defined(__mips__) && !defined(__arm__) */

⌨️ 快捷键说明

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