📄 4.html
字号:
int sys_getgid(void)<br>{<br>return current->gid;<br>}<br>int sys_getegid(void)<br>{<br>return current->egid;<br>}<br>int sys_nice(long increment)<br>{<br>if (current->priority-increment>0)<br>current->priority -= increment;<br>return 0;<br>}<br>int sys_signal(long signal,long addr,long restorer)<br>{<br>long i;<br>switch (signal) {<br>case SIGHUP: case SIGINT: case SIGQUIT: case SIGILL:<br>case SIGTRAP: case SIGABRT: case SIGFPE: case SIGUSR1:<br>case SIGSEGV: case SIGUSR2: case SIGPIPE: case SIGALRM:<br>case SIGCHLD:<br>i=(long) current->sig_fn[signal-1];<br>current->sig_fn[signal-1] = (fn_ptr) addr;<br>current->sig_restorer = (fn_ptr) restorer;<br>return i;<br>default: return -1;<br>}<br>}<br>void sched_init(void)<br>{<br>int i;<br>struct desc_struct * p;<br>set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));@@init task tss<br>set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));@@init ldt<br>p = gdt+2+FIRST_TSS_ENTRY;<br>for(i=1;i task[i] = NULL;<br>p->a=p->b=0;<br>p++;<br>p->a=p->b=0;<br>p++;<br>}<br>ltr(0); @@调入task 0的tss<br>lldt(0); @@调入task 0的ldt<br>outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */<br>outb_p(LATCH & 0xff , 0x40); /* LSB */<br>outb(LATCH >> 8 , 0x40); /* MSB */<br>set_intr_gate(0x20,&timer_interrupt); @@irq 0 时钟中断<br>outb(inb_p(0x21)&~0x01,0x21);<br>set_system_gate(0x80,&system_call);<br>}<p><p><br><center><A HREF="#Content">[目录]</A></center><hr><br><A NAME="I410" ID="I410"></A><center><b><font size=+2>进程信号队列</font></b></center><br> 每个进程具有一个sigpending结构所描述的信号队列,它有3个成员,head指向第一个sigqueue成员,tail指向最末的sigqueue成员的next指针,signal描述了此队列中的信号集.<p>static int<br>send_signal(int sig, struct siginfo *info, struct sigpending *signals);<br>将信号sig和对应的消息结构info添加到信号队列signal中.<br>static int<br>collect_signal(int sig, struct sigpending *list, siginfo_t *info);<br>返回信号sig在队列list中的信息info.<p><br>struct task_struct {<br> ...<br> struct sigpending pending;<br> ...<br>};<br>struct sigpending {<br> struct sigqueue *head, **tail;<br> sigset_t signal;<br>};<br>struct sigqueue {<br> struct sigqueue *next;<br> siginfo_t info;<br> };<br>// kernel/signal.c<br>static int<br>send_signal(int sig, struct siginfo *info, struct sigpending *signals)<br>{<br> struct sigqueue * q = NULL;<br> /* Real-time signals must be queued if sent by sigqueue, or<br> some other real-time mechanism. It is implementation<br> defined whether kill() does so. We attempt to do so, on<br> the principle of least surprise, but since kill is not<br> allowed to fail with EAGAIN when low on memory we just<br> make sure at least one signal gets delivered and don't<br> pass on the info struct. */<p> if (atomic_read(&nr_queued_signals) < max_queued_signals) {<br> q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);<br> }<br> // nr_queued_signals和max_queued_signals用来限制全局sigqueue成员的数目<br> if (q) {<br> atomic_inc(&nr_queued_signals);<br> q->next = NULL;<br> *signals->tail = q;<br> signals->tail = &q->next; tail总是指向最末的信号成员的next指针 switch ((unsign<br>ed long) info)<br> {<br> case 0:<br> // info参数如果为0,表示信号来源于当前用户进程 q->info.si_signo =<br>sig;<br> q->info.si_errno = 0;<br> q->info.si_code = SI_USER;<br> q->info.si_pid = current->pid;<br> q->info.si_uid = current->uid;<br> break;<br> case 1:<br> // info参数如果为1,表示信号来源于内核本身 q->info.si_signo = sig;<br> q->info.si_errno = 0;<br> q->info.si_code = SI_KERNEL;<br> q->info.si_pid = 0;<br> q->info.si_uid = 0;<br> break;<br> default:<br> // 否则从info指针中拷贝信号<br> copy_siginfo(&q->info, info);<br> break;<br> }<br> }<br> else if (sig >= SIGRTMIN && info && (unsigned long)info != 1 && info-><br>si_code != SI_USER)<br> {<br> ; 如果该信号是内核发出的实时信号,就返回错误码<br> /*<br> * Queue overflow, abort. We may abort if the signal was rt<br> * and sent by user using something other than kill().<br> */<br> return -EAGAIN;<br> }<br> sigaddset(&signals->signal, sig); 将sig号标记在队列的信号集上<br> return 0;<br>}<br>static int<br>collect_signal(int sig, struct sigpending *list, siginfo_t *info)<br>{<br> if (sigismember(&list->signal, sig)) {<br> /* Collect the siginfo appropriate to this signal. */ struct sigqueue *q, **<br>pp;<br> pp = &list->head; pp指向第一个信号成员的next指针<br> while ((q = *pp) != NULL) {<br> if (q->info.si_signo == sig) goto found_it;<br> pp = &q->next;<br> }<br> /* Ok, it wasn't in the queue. We must have<br> been out of queue space. So zero out the<br> info.<br> */<br> sigdelset(&list->signal, sig);<br> info->si_signo = sig;<br> info->si_errno = 0;<br> info->si_code = 0;<br> info->si_pid = 0;<br> info->si_uid = 0;<br> return 1;<br> found_it:<br> // 将找到信号成员从信号队列中删除<br> if ((*pp = q->next) == NULL)<br> list->tail = pp;<br> /* Copy the sigqueue information and free the queue entry */<br> copy_siginfo(info, &q->info);<br> kmem_cache_free(sigqueue_cachep,q);<br> atomic_dec(&nr_queued_signals);<br> /* Non-RT signals can exist multiple times.. */<br> if (sig >= SIGRTMIN) {<br> while ((q = *pp) != NULL) {<br> if (q->info.si_signo == sig) goto found_another;<br> pp = &q->next;<br> }<br> }<br> sigdelset(&list->signal, sig);<br> found_another:<br> return 1;<br> }<br> return 0;<br>}<p><p><p><center><A HREF="#Content">[目录]</A></center><hr><br><A NAME="I411" ID="I411"></A><center><b><font size=+2>SMP</font></b></center><br> 多处理机系统正在变得越来越普通。尽管大多数用户空间代码仍将完美地运行,而且有些情况下不需要增加额外的代码就能利用SMP特性的优势,但是内核空间代码必须编写成具备“SMP意识”且是“SMP安全的”。以下几段文字解释如何去做。<p>问题<p> 当有多个CPU时,同样的代码可能同时在两个或多个CPU上执行。这在如下所示用于初始化某个图像设备的例程中可能会出问题。<br> void init_hardware(void)<br> {<br> outb(0x1, hardware_base + 0x30);<br> outb(0x2, hardware_base + 0x30);<br> outb(0x3, hardware_base + 0x30);<br> outb(0x4, hardware_base + 0x30);<br> }<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -