- 浏览: 321846 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
JQ_AK47:
...
Linux下直接发送以太包 -
winsen2009:
谢谢分享,如果能再来一个列子就更好了,刚接触看完还是不懂的用
UNPv1_r3读书笔记: SCTP编程
本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,
严禁用于任何商业用途。
msn: yfydz_no1@hotmail.com
来源:http://yfydz.cublog.cn
严禁用于任何商业用途。
msn: yfydz_no1@hotmail.com
来源:http://yfydz.cublog.cn
1. 前言 信号是类UNIX系统中一个重要的进程控制方法,向中断一样,可通过向进程发送不同的信号临时中断 程序的正常运行而进入信号处理程序或执行缺省的信号响应,如重新更新程序配置、终止进程等。 在用户空间中,信号处理接口是通过一系列系统调用来实现的,包括signal, sigaction, sigsuspend, sigaltstack等,进程可通过以上这些接口定义进程的信号处理函数。如果要向其他进 程发信号,可通过kill系统调用实现。 在内核中对信号的处理程序主要定义在 kernel/signal.c, arch/***/kernel/signal.c等文件中,头 文件在 include/linux/signal.h, include/asm/signal.h等。 以下内核代码版本为2.6.19.2。 2. 数据结构 2.1 信号自身基本定义 用于定义信号处理 /* include/asm-generic/signal.h */ // 信号处理函数格式 typedef void __signalfn_t(int); typedef __signalfn_t __user *__sighandler_t; // 信号恢复函数 typedef void __restorefn_t(void); typedef __restorefn_t __user *__sigrestore_t; // 三个预定义的信号处理函数值 #define SIG_DFL ((__force __sighandler_t)0) /* default signal handling */ #define SIG_IGN ((__force __sighandler_t)1) /* ignore signal */ #define SIG_ERR ((__force __sighandler_t)-1) /* error return from signal */ /* include/asm-i386/signal.h */ #define _NSIG 64 #define _NSIG_BPW 32 #define _NSIG_WORDS (_NSIG / _NSIG_BPW) typedef unsigned long old_sigset_t; /* at least 32 bits */ // 信号集, 最多64个信号 typedef struct { unsigned long sig[_NSIG_WORDS]; } sigset_t; // 老的信号处理结构 struct old_sigaction { __sighandler_t sa_handler; old_sigset_t sa_mask; unsigned long sa_flags; __sigrestore_t sa_restorer; }; // 信号处理结构 struct sigaction { // 信号处理函数 __sighandler_t sa_handler; // 标志 unsigned long sa_flags; // 信号恢复函数 __sigrestore_t sa_restorer; // 信号集 sigset_t sa_mask; /* mask last for extensibility */ }; // 另一个定义 struct k_sigaction { struct sigaction sa; }; 2.2 信号信息结构定义 用于发送信号 /* include/asm-generic/siginfo.h */ typedef struct siginfo { int si_signo; int si_errno; int si_code; union { int _pad[SI_PAD_SIZE]; /* kill() */ struct { pid_t _pid; /* sender's pid */ __ARCH_SI_UID_T _uid; /* sender's uid */ } _kill; /* POSIX.1b timers */ struct { timer_t _tid; /* timer id */ int _overrun; /* overrun count */ char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)]; sigval_t _sigval; /* same as below */ int _sys_private; /* not to be passed to user */ } _timer; /* POSIX.1b signals */ struct { pid_t _pid; /* sender's pid */ __ARCH_SI_UID_T _uid; /* sender's uid */ sigval_t _sigval; } _rt; /* SIGCHLD */ struct { pid_t _pid; /* which child */ __ARCH_SI_UID_T _uid; /* sender's uid */ int _status; /* exit code */ clock_t _utime; clock_t _stime; } _sigchld; /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ struct { void __user *_addr; /* faulting insn/memory ref. */ #ifdef __ARCH_SI_TRAPNO int _trapno; /* TRAP # which caused the signal */ #endif } _sigfault; /* SIGPOLL */ struct { __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */ int _fd; } _sigpoll; } _sifields; } siginfo_t; 3. 定义信号处理函数 signal系统调用在内核中对应的是sys_signal,sigaction对应的是sys_sysaction: /* kernel/signal.c */ /* * For backwards compatibility. Functionality superseded by sigaction. */ // signal函数已经只是为了后向兼容了,以后尽量还是使用sigaction实现为好 asmlinkage unsigned long sys_signal(int sig, __sighandler_t handler) { struct k_sigaction new_sa, old_sa; int ret; // 填写新的信号处理结构参数 // 最重要的是handler参数 new_sa.sa.sa_handler = handler; new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK; sigemptyset(&new_sa.sa.sa_mask); // 进入do_sigaction函数处理 ret = do_sigaction(sig, &new_sa, &old_sa); // 如果返回值为0(成功), 返回原来的信号处理函数 return ret ? ret : (unsigned long)old_sa.sa.sa_handler; } /* arch/i386/kernel/signal.c */ // 注意输入的是老的信号处理结构 asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) { struct k_sigaction new_ka, old_ka; int ret; // act相当于新的信号处理结构定义 if (act) { // 从用户层空间拷贝信号处理结构参数 old_sigset_t mask; if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) return -EFAULT; __get_user(new_ka.sa.sa_flags, &act->sa_flags); __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); } // 进入do_sigaction函数处理 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); // 返回值为0(成功)时,返回老的信号处理结构信息 if (!ret && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) return -EFAULT; __put_user(old_ka.sa.sa_flags, &oact->sa_flags); __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; } 这两个函数基本相同, 但一个是只处理一个信号处理函数,另一个则是处理一个信号处理结构, 参数 要复杂一些,但这两个函数的核心都是do_sysaction: /* kernel/signal.c */ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) { struct k_sigaction *k; sigset_t mask; // 检查一下参数是否合法 if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig))) return -EINVAL; // k指向进程原来的信号处理结构 k = ¤t->sighand->action[sig-1]; spin_lock_irq(¤t->sighand->siglock); if (signal_pending(current)) { // 目前进程在信号处理状态中 // 此时不能设置信号处理程序 /* * If there might be a fatal signal pending on multiple * threads, make sure we take it before changing the action. */ spin_unlock_irq(¤t->sighand->siglock); return -ERESTARTNOINTR; } // 将进程原来的信号处理结构备份到函数参数指定的原信号处理结构中 if (oact) *oact = *k; // 要更新信号处理 if (act) { // SIGKILL和SIGSTOP这两个信号是不能定义新的处理函数的 // 相应标识始终被清除,因此即使设了也没用 sigdelsetmask(&act->sa.sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP)); // 将新信号结构复制到进程对应的信号处理结构中 *k = *act; /* * 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" */ if (act->sa.sa_handler == SIG_IGN || (act->sa.sa_handler == SIG_DFL && sig_kernel_ignore(sig))) { // 如果新的信号处理函数是忽略该信号 struct task_struct *t = current; // 清空信号掩码 sigemptyset(&mask); // 设置掩码中相应信号的位 sigaddset(&mask, sig); // 从该进程的信号队列中清除该信号 rm_from_queue_full(&mask, &t->signal->shared_pending); // 从该进程的所有子线程的信号队列中清除该信号 do { rm_from_queue_full(&mask, &t->pending); recalc_sigpending_tsk(t); t = next_thread(t); } while (t != current); } } spin_unlock_irq(¤t->sighand->siglock); return 0; } 4. 发送信号 发送信号是通过kill(2)系统调用实现的,内核对应的处理函数是sys_kill: /* kernel/signal.c */ asmlinkage long sys_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->tgid; info.si_uid = current->uid; // 向pid进程发送信号 return kill_something_info(sig, &info, pid); } /* kernel/signal.h */ /* * 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) { // pid为0, 是向一个进程组发信号 return kill_pg_info(sig, info, process_group(current)); } else if (pid == -1) { // pid为-1. 向所有其他组的进程发送信号 int retval = 0, count = 0; struct task_struct * p; read_lock(&tasklist_lock); for_each_process(p) { if (p->pid > 1 && p->tgid != current->tgid) { int err = group_send_sig_info(sig, info, p); ++count; if (err != -EPERM) retval = err; } } read_unlock(&tasklist_lock); return count ? retval : -ESRCH; } else if (pid < 0) { // 其他的负pid值,将pid取反为正值后向进程组发送信号 return kill_pg_info(sig, info, -pid); } else { // 一般情况, 向指定pid的进程发送信号 return kill_proc_info(sig, info, pid); } } 函数调用流程图: kill_proc_info kill_pg_info | | V V kill_pid_info __kill_pg_info | | | V | __kill_pgrp_info | | +----------------------+ | V group_send_sig_info | V __group_send_sig_info | V send_signal /* kernel/signal.c */ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, struct sigpending *signals) { struct sigqueue * q = NULL; int ret = 0; /* * fast-pathed signals for kernel-internal things like SIGSTOP * or SIGKILL. */ // 强制发送信号(SIGKILL或SIGSTOP), 直接发送 if (info == SEND_SIG_FORCED) goto out_set; /* Real-time signals must be queued if sent by sigqueue, or some other real-time mechanism. It is implementation defined whether kill() does so. We attempt to do so, on the principle of least surprise, but since kill is not allowed to fail with EAGAIN when low on memory we just make sure at least one signal gets delivered and don't pass on the info struct. */ // 分配信号队列结构, 从sigqueue_cachep中分配(这个一个kmem_cache) q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN && (is_si_special(info) || info->si_code >= 0))); if (q) { // 分配成功 // 将该信号队列挂接到待发送信号链表末尾, 注意add_list是添加到链表头的 list_add_tail(&q->list, &signals->list); switch ((unsigned long) info) { // 先看是否是几个特殊的info值然后填写相应的信号信息结构参数 case (unsigned long) SEND_SIG_NOINFO: // 信号值 q->info.si_signo = sig; q->info.si_errno = 0; q->info.si_code = SI_USER; q->info.si_pid = current->pid; q->info.si_uid = current->uid; break; case (unsigned long) SEND_SIG_PRIV: // 信号值 q->info.si_signo = sig; q->info.si_errno = 0; q->info.si_code = SI_KERNEL; q->info.si_pid = 0; q->info.si_uid = 0; break; default: // 如是普通情况,复制信号信息 copy_siginfo(&q->info, info); break; } } else if (!is_si_special(info)) { // 队列满了,普通用户的信号就被忽略,返回错误 if (sig >= SIGRTMIN && info->si_code != SI_USER) /* * Queue overflow, abort. We may abort if the signal was rt * and sent by user using something other than kill(). */ return -EAGAIN; } out_set: // 设置信号集中相应的信号标志 sigaddset(&signals->signal, sig); return ret; } /* include/asm-i386/signal.h */ #define sigaddset(set,sig) \ (__builtin_constant_p(sig) ? \ __const_sigaddset((set),(sig)) : \ __gen_sigaddset((set),(sig))) static __inline__ void __gen_sigaddset(sigset_t *set, int _sig) { __asm__("btsl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc"); } static __inline__ void __const_sigaddset(sigset_t *set, int _sig) { unsigned long sig = _sig - 1; set->sig[sig / _NSIG_BPW] |= 1 << (sig % _NSIG_BPW); } 5. 处理信号 /* arch/i386/kernel/signal.c */ /* * notification of userspace execution resumption * - triggered by the TIF_WORK_MASK flags */ __attribute__((regparm(3))) void do_notify_resume(struct pt_regs *regs, void *_unused, __u32 thread_info_flags) { /* Pending single-step? */ if (thread_info_flags & _TIF_SINGLESTEP) { regs->eflags |= TF_MASK; clear_thread_flag(TIF_SINGLESTEP); } /* deal with pending signal delivery */ // 派发待发送的信号 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) do_signal(regs); clear_thread_flag(TIF_IRET); } /* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ static void fastcall do_signal(struct pt_regs *regs) { siginfo_t info; int signr; struct k_sigaction ka; sigset_t *oldset; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. vm86 regs switched out by assembly code * before reaching here, so testing against kernel * CS suffices. */ // 信号处理函数是在用户空间 if (!user_mode(regs)) return; // 原先的信息集指针 if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; // 找要发送的信号 signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { // 找到一个信号 /* Reenable any watchpoints before delivering the * signal to user space. The processor register will * have been cleared if the watchpoint triggered * inside the kernel. */ if (unlikely(current->thread.debugreg[7])) set_debugreg(current->thread.debugreg[7], 7); /* Whee! Actually deliver the signal. */ // 处理信号 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } return; } // 无信号的情况 /* Did we come from a system call? */ if (regs->orig_eax >= 0) { /* Restart the system call - no handlers present */ switch (regs->eax) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs->eax = regs->orig_eax; regs->eip -= 2; break; case -ERESTART_RESTARTBLOCK: regs->eax = __NR_restart_syscall; regs->eip -= 2; break; } } /* if there's no signal to deliver, we just put the saved sigmask * back */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } /* * OK, we're invoking a handler */ static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) { int ret; /* Are we from a system call? */ if (regs->orig_eax >= 0) { // 判断当前是否在系统调用中 /* If so, check system call restarting.. */ switch (regs->eax) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->eax = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { regs->eax = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: regs->eax = regs->orig_eax; regs->eip -= 2; } } /* * If TF is set due to a debugger (PT_DTRACE), clear the TF flag so * that register information in the sigcontext is correct. */ if (unlikely(regs->eflags & TF_MASK) && likely(current->ptrace & PT_DTRACE)) { current->ptrace &= ~PT_DTRACE; regs->eflags &= ~TF_MASK; } /* Set up the stack frame */ // 建立进入信号处理函数前堆栈帧 if (ka->sa.sa_flags & SA_SIGINFO) ret = setup_rt_frame(sig, ka, info, oldset, regs); else ret = setup_frame(sig, ka, oldset, regs); if (ret == 0) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NODEFER)) sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } return ret; } /* kernel/signal.c */ // 找要发送的信号 int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie) { sigset_t *mask = ¤t->blocked; int signr = 0; try_to_freeze(); relock: spin_lock_irq(¤t->sighand->siglock); for (;;) { struct k_sigaction *ka; // unlikely的处理就是大部分情况下可忽略 if (unlikely(current->signal->group_stop_count > 0) && handle_group_stop()) goto relock; // 从当前进程的信号队列中取信号 signr = dequeue_signal(current, mask, info); if (!signr) // 无信号 break; /* will return 0 */ // 有信号 if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { // 当前进程是被跟踪调试中 ptrace_signal_deliver(regs, cookie); /* Let the debugger run. */ ptrace_stop(signr, signr, info); /* We're back. Did the debugger cancel the sig? */ signr = current->exit_code; if (signr == 0) continue; current->exit_code = 0; /* Update the siginfo structure if the signal has changed. If the debugger wanted something specific in the siginfo structure then it should have updated *info via PTRACE_SETSIGINFO. */ if (signr != info->si_signo) { info->si_signo = signr; info->si_errno = 0; info->si_code = SI_USER; info->si_pid = current->parent->pid; info->si_uid = current->parent->uid; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { specific_send_sig_info(signr, info, current); continue; } } // 获取当前进程的信号处理函数 ka = ¤t->sighand->action[signr-1]; if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ // 该信号是要忽略的,重新找下一信号 continue; if (ka->sa.sa_handler != SIG_DFL) { // 定义了具体的函数处理函数, 复制要返回信号处理结构 /* Run the handler. */ *return_ka = *ka; if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; break; /* will return non-zero "signr" value */ } /* * Now we are doing the default action for this signal. */ // 否则执行系统缺省的信号处理 if (sig_kernel_ignore(signr)) /* Default is nothing. */ continue; /* Init gets no signals it doesn't want. */ if (current == child_reaper) continue; if (sig_kernel_stop(signr)) { /* * The default action is to stop all threads in * the thread group. The job control signals * do nothing in an orphaned pgrp, but SIGSTOP * always works. Note that siglock needs to be * dropped during the call to is_orphaned_pgrp() * because of lock ordering with tasklist_lock. * This allows an intervening SIGCONT to be posted. * We need to check for that and bail out if necessary. */ if (signr != SIGSTOP) { spin_unlock_irq(¤t->sighand->siglock); /* signals can be posted during this window */ if (is_orphaned_pgrp(process_group(current))) goto relock; spin_lock_irq(¤t->sighand->siglock); } if (likely(do_signal_stop(signr))) { /* It released the siglock. */ goto relock; } /* * We didn't actually stop, due to a race * with SIGCONT or something like that. */ continue; } spin_unlock_irq(¤t->sighand->siglock); /* * Anything else is fatal, maybe with a core dump. */ current->flags |= PF_SIGNALED; if (sig_kernel_coredump(signr)) { /* * If it was able to dump core, this kills all * other threads in the group and synchronizes with * their demise. If we lost the race with another * thread getting here, it set group_exit_code * first and our do_group_exit call below will use * that value and ignore the one we pass it. */ do_coredump((long)signr, signr, regs); } /* * Death signals, no core dump. */ do_group_exit(signr); /* NOTREACHED */ } spin_unlock_irq(¤t->sighand->siglock); return signr; } 6. 结论 Linux下的信号实现基本符合了APUE中对信号处理的描述, SIGKILL/SIGSTOP不可忽略, 发送给某进程的信号会排队, 信号可能会丢失等等.
发表评论
-
Linux内核中流量控制(24)
2011-01-10 16:33 2245本文档的Copyleft归yfydz所 ... -
Linux内核中流量控制(23)
2011-01-10 16:30 1532本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(22)
2011-01-10 16:29 1980本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(21)
2011-01-10 16:28 1401本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(20)
2011-01-10 16:27 1567本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(19)
2011-01-10 16:27 2022本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(18)
2011-01-10 16:26 1616Linux内核中流量控制(18) ... -
Linux内核中流量控制(17)
2011-01-10 16:25 1991本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(16)
2011-01-10 16:25 1849本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(15)
2011-01-10 16:24 1979本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(14)
2011-01-10 16:23 2001本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(13)
2011-01-10 16:22 2686本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(12)
2011-01-10 16:21 2166本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(11)
2011-01-10 16:21 3289本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(10)
2011-01-10 16:20 2040本文档的Copyleft归yfydz所 ... -
Linux内核中流量控制(9)
2011-01-10 16:19 1876本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(8)
2011-01-10 16:18 1544本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(7)
2011-01-10 16:18 2973本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(6)
2011-01-10 16:17 1539本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(5)
2011-01-10 16:16 1767本文档的Copyleft归yfydz所有,使用GPL发布,可以 ...
相关推荐
下面我们将深入探讨Linux信号机制的各个方面。 1. **信号定义与类型**:Linux系统定义了一系列预定义的信号,如SIGINT(中断,由Ctrl+C产生)、SIGTERM(正常终止请求)、SIGKILL(强制终止,无法被捕获或忽略)...
### 第9章Linux信号与定时器 #### 一、进程间通信与信号 ...总之,Linux信号和定时器是实现进程间通信和时间管理的关键组件。通过深入理解它们的工作原理和使用方法,开发者可以构建出更加健壮和高效的Linux应用程序。
### Linux信号量详解 #### 一、信号量概念与历史 1965年,E.W.Dijkstra引入了信号量的概念,这是一种操作系统中用于实现进程间互斥和同步的重要机制。信号量本质上是一个包含了非负整型变量的数据结构,伴随着两个...
该文档介绍了如何在linux操作系统中使用信号量实现不同进程间的同步功能。
【标题】:“Linux信号机制解析.pdf” 【描述】:“Linux信号机制解析.pdf” 【标签】:“Linux 操作系统 系统开发 参考文献 专业指导” 【部分内容】:分析了信号机制的特性,指出了早期信号机制的不足、原因...
《Linux内核设计与实现》是理解Linux操作系统内核架构和技术细节的重要参考资料,特别是第三版中文高清版,为读者提供了全面且深入的内核解析。这本书由Robert Love编写,是学习Linux内核不可或缺的经典之作。以下将...
为了实现信号量功能,我们需要定义一个数据结构来表示信号量状态。这个数据结构需要包含以下字段: - **count**:一个整型变量,表示当前可用的信号量数量。通常初始化为1表示互斥信号量,也可以初始化为其他正值...
本项目关注的是如何使用C++编程语言在Linux系统中实现ICMP功能,具体表现为一个简单的"PING"程序。下面我们将深入探讨这个主题,讲解涉及的知识点。 首先,我们要理解ICMP协议。它是一种“无连接”的协议,用于传输...
### Linux信号详解 #### 一、引言 在Linux系统中,信号是一种进程间通信机制,主要用于异步通知进程发生了某种事件。通过本篇文章,我们将详细介绍Linux中的信号及其作用。 #### 二、信号概述 Linux信号是操作...
### Linux信号机制详解 ...通过以上介绍,我们可以看出Linux信号机制虽然复杂,但在实际应用中提供了丰富的功能和灵活性。无论是对于系统的维护还是应用程序的开发,理解信号的工作原理都是非常重要的。
Linux信号机制是操作系统内核中用于进程间通信和异常处理的一种机制。它允许一个进程向另一个进程发送消息,这些消息可以是关于特定事件的通知,或者是请求执行特定操作的命令。在Linux系统中,信号机制是基于POSIX...
总结来说,Linux信号机制提供了进程间通信的基础,它不仅能够帮助我们处理异常情况,还能够用于控制进程行为和协调进程间的同步。`signalWcg.c`和`signalWcgClient.c`的示例可能展示了如何创建信号处理器、发送和...
在Linux系统中实现Wi-Fi功能是一项涉及网络接口、驱动程序、内核模块和用户空间工具的重要任务。Linux下的Wi-Fi实现通常需要理解无线网络的基本原理、Linux内核的网络子系统以及如何配置和管理无线连接。以下将详细...
此外,内核还实现了信号量、互斥锁等同步机制,确保并发执行的进程之间能够正确通信和协调。 内存管理是Linux内核中的另一个关键部分。内核使用分页技术将物理内存划分为固定大小的页,每个页都有一个对应的页表项...
服务器端主要完成服务器端的初始化及监听、消息的存储和转发、系统消息的发送和信息管理等功能,使用Linux下的C语言实现。 知识点一:聊天系统的设计与实现 * 聊天系统的设计目标:实现基于Linux操作系统的聊天...
通过本篇文章,我们将深入探讨Linux信号的基础概念、不同信号的功能及其应用场景。 #### 二、信号概述 Linux信号是由内核发送给进程的一种特殊类型的信息。信号可用于多种场景,例如:程序错误处理、用户输入处理...
"Linux内核设计与实现" 本节将对Linux内核设计与实现进行详细的分析和解释,主要集中在进程管理方面,特别是fork()函数的两次返回情况。 fork()函数的两次返回 fork()函数是Linux内核中用于创建新进程的系统调用...