?? signal.c
字號(hào):
/** linux/kernel/signal.c** (C) 1991 Linus Torvalds*/#include <linux/sched.h> // 調(diào)度程序頭文件,定義了任務(wù)結(jié)構(gòu)task_struct、初始任務(wù)0 的數(shù)據(jù),// 還有一些有關(guān)描述符參數(shù)設(shè)置和獲取的嵌入式匯編函數(shù)宏語(yǔ)句。#include <linux/kernel.h> // 內(nèi)核頭文件。含有一些內(nèi)核常用函數(shù)的原形定義。#include <asm/segment.h> // 段操作頭文件。定義了有關(guān)段寄存器操作的嵌入式匯編函數(shù)。#include <signal.h> // 信號(hào)頭文件。定義信號(hào)符號(hào)常量,信號(hào)結(jié)構(gòu)以及信號(hào)操作函數(shù)原型。volatile void do_exit (int error_code); // 前面的限定符volatile 要求編譯器不要對(duì)其進(jìn)行優(yōu)化。// 獲取當(dāng)前任務(wù)信號(hào)屏蔽位圖(屏蔽碼)。intsys_sgetmask (){ return current->blocked;}// 設(shè)置新的信號(hào)屏蔽位圖。SIGKILL 不能被屏蔽。返回值是原信號(hào)屏蔽位圖。intsys_ssetmask (int newmask){ int old = current->blocked; current->blocked = newmask & ~(1 << (SIGKILL - 1)); return old;}// 復(fù)制sigaction 數(shù)據(jù)到fs 數(shù)據(jù)段to 處。。static inline voidsave_old (char *from, char *to){ int i; verify_area (to, sizeof (struct sigaction)); // 驗(yàn)證to 處的內(nèi)存是否足夠。 for (i = 0; i < sizeof (struct sigaction); i++) { put_fs_byte (*from, to); // 復(fù)制到fs 段。一般是用戶數(shù)據(jù)段。 from++; // put_fs_byte()在include/asm/segment.h 中。 to++; }}// 把sigaction 數(shù)據(jù)從fs 數(shù)據(jù)段from 位置復(fù)制到to 處。static inline voidget_new (char *from, char *to){ int i; for (i = 0; i < sizeof (struct sigaction); i++) *(to++) = get_fs_byte (from++);}// signal()系統(tǒng)調(diào)用。類似于sigaction()。為指定的信號(hào)安裝新的信號(hào)句柄(信號(hào)處理程序)。// 信號(hào)句柄可以是用戶指定的函數(shù),也可以是SIG_DFL(默認(rèn)句柄)或SIG_IGN(忽略)。// 參數(shù)signum --指定的信號(hào);handler -- 指定的句柄;restorer –原程序當(dāng)前執(zhí)行的地址位置。// 函數(shù)返回原信號(hào)句柄。intsys_signal (int signum, long handler, long restorer){ struct sigaction tmp; if (signum < 1 || signum > 32 || signum == SIGKILL) // 信號(hào)值要在(1-32)范圍內(nèi), return -1; // 并且不得是SIGKILL。 tmp.sa_handler = (void (*)(int)) handler; // 指定的信號(hào)處理句柄。 tmp.sa_mask = 0; // 執(zhí)行時(shí)的信號(hào)屏蔽碼。 tmp.sa_flags = SA_ONESHOT | SA_NOMASK; // 該句柄只使用1 次后就恢復(fù)到默認(rèn)值,// 并允許信號(hào)在自己的處理句柄中收到。 tmp.sa_restorer = (void (*)(void)) restorer; // 保存返回地址。 handler = (long) current->sigaction[signum - 1].sa_handler; current->sigaction[signum - 1] = tmp; return handler;}// sigaction()系統(tǒng)調(diào)用。改變進(jìn)程在收到一個(gè)信號(hào)時(shí)的操作。signum 是除了SIGKILL 以外的任何// 信號(hào)。[如果新操作(action)不為空]則新操作被安裝。如果oldaction 指針不為空,則原操作// 被保留到oldaction。成功則返回0,否則為-1。intsys_sigaction (int signum, const struct sigaction *action, struct sigaction *oldaction){ struct sigaction tmp;// 信號(hào)值要在(1-32)范圍內(nèi),并且信號(hào)SIGKILL 的處理句柄不能被改變。 if (signum < 1 || signum > 32 || signum == SIGKILL) return -1;// 在信號(hào)的sigaction 結(jié)構(gòu)中設(shè)置新的操作(動(dòng)作)。 tmp = current->sigaction[signum - 1]; get_new ((char *) action, (char *) (signum - 1 + current->sigaction));// 如果oldaction 指針不為空的話,則將原操作指針保存到oldaction 所指的位置。 if (oldaction) save_old ((char *) &tmp, (char *) oldaction);// 如果允許信號(hào)在自己的信號(hào)句柄中收到,則令屏蔽碼為0,否則設(shè)置屏蔽本信號(hào)。 if (current->sigaction[signum - 1].sa_flags & SA_NOMASK) current->sigaction[signum - 1].sa_mask = 0; else current->sigaction[signum - 1].sa_mask |= (1 << (signum - 1)); return 0;}// 系統(tǒng)調(diào)用中斷處理程序中真正的信號(hào)處理程序(在kernel/system_call.s,119 行)。// 該段代碼的主要作用是將信號(hào)的處理句柄插入到用戶程序堆棧中,并在本系統(tǒng)調(diào)用結(jié)束// 返回后立刻執(zhí)行信號(hào)句柄程序,然后繼續(xù)執(zhí)行用戶的程序。voiddo_signal (long signr, long eax, long ebx, long ecx, long edx, long fs, long es, long ds, long eip, long cs, long eflags, unsigned long *esp, long ss){ unsigned long sa_handler; long old_eip = eip; struct sigaction *sa = current->sigaction + signr - 1; //current->sigaction[signu-1]。 int longs; unsigned long *tmp_esp; sa_handler = (unsigned long) sa->sa_handler;// 如果信號(hào)句柄為SIG_IGN(忽略),則返回;如果句柄為SIG_DFL(默認(rèn)處理),則如果信號(hào)是// SIGCHLD 則返回,否則終止進(jìn)程的執(zhí)行 if (sa_handler == 1) return; if (!sa_handler) { if (signr == SIGCHLD) return; else do_exit (1 << (signr - 1)); // [?? 為什么以信號(hào)位圖為參數(shù)?不為什么!??]// 這里應(yīng)該是do_exit(1<<signr))。 }// 如果該信號(hào)句柄只需使用一次,則將該句柄置空(該信號(hào)句柄已經(jīng)保存在sa_handler 指針中)。 if (sa->sa_flags & SA_ONESHOT) sa->sa_handler = NULL;// 下面這段代碼將信號(hào)處理句柄插入到用戶堆棧中,同時(shí)也將sa_restorer,signr,進(jìn)程屏蔽碼(如果// SA_NOMASK 沒(méi)置位),eax,ecx,edx 作為參數(shù)以及原調(diào)用系統(tǒng)調(diào)用的程序返回指針及標(biāo)志寄存器值// 壓入堆棧。因此在本次系統(tǒng)調(diào)用中斷(0x80)返回用戶程序時(shí)會(huì)首先執(zhí)行用戶的信號(hào)句柄程序,然后// 再繼續(xù)執(zhí)行用戶程序。// 將用戶調(diào)用系統(tǒng)調(diào)用的代碼指針eip 指向該信號(hào)處理句柄。 *(&eip) = sa_handler;// 如果允許信號(hào)自己的處理句柄收到信號(hào)自己,則也需要將進(jìn)程的阻塞碼壓入堆棧。 longs = (sa->sa_flags & SA_NOMASK) ? 7 : 8;// 將原調(diào)用程序的用戶的堆棧指針向下擴(kuò)展7(或8)個(gè)長(zhǎng)字(用來(lái)存放調(diào)用信號(hào)句柄的參數(shù)等),// 并檢查內(nèi)存使用情況(例如如果內(nèi)存超界則分配新頁(yè)等)。 *(&esp) -= longs; verify_area (esp, longs * 4);// 在用戶堆棧中從下到上存放sa_restorer, 信號(hào)signr, 屏蔽碼blocked(如果SA_NOMASK 置位),// eax, ecx, edx, eflags 和用戶程序原代碼指針。 tmp_esp = esp; put_fs_long ((long) sa->sa_restorer, tmp_esp++); put_fs_long (signr, tmp_esp++); if (!(sa->sa_flags & SA_NOMASK)) put_fs_long (current->blocked, tmp_esp++); put_fs_long (eax, tmp_esp++); put_fs_long (ecx, tmp_esp++); put_fs_long (edx, tmp_esp++); put_fs_long (eflags, tmp_esp++); put_fs_long (old_eip, tmp_esp++); current->blocked |= sa->sa_mask; // 進(jìn)程阻塞碼(屏蔽碼)添上sa_mask 中的碼位。}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -