linux-exit.c

來源:互聯網
上載者:User
/* *  linux/kernel/exit.c *         //--任務終止和退出的有關處理事宜,包括釋放,會話,終止和程式退出處理函數以及殺死進程 *  (C) 1991  Linus Torvalds */#define DEBUG_PROC_TREE#include <errno.h>#include <signal.h>#include <sys/wait.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/tty.h>#include <asm/segment.h>int sys_pause(void);int sys_close(int fd);void release(struct task_struct * p)    //--根據進程的任務資料結構指標,{                                    //--在任務數組中刪除指定的進程指標,釋放相關記憶體頁    int i;                            //--並立刻讓核心重新調度任務的運行。    if (!p)        return;    if (p == current) {        printk("task releasing itself/n/r");        return;    }    for (i=1 ; i<NR_TASKS ; i++)        if (task[i]==p) {            task[i]=NULL;            /* Update links */            if (p->p_osptr)                p->p_osptr->p_ysptr = p->p_ysptr;            if (p->p_ysptr)                p->p_ysptr->p_osptr = p->p_osptr;            else                p->p_pptr->p_cptr = p->p_osptr;            free_page((long)p);                    //--釋放記憶體頁            schedule();                            //--重新調度任務            return;        }    panic("trying to release non-existent task");}#ifdef DEBUG_PROC_TREE/* * Check to see if a task_struct pointer is present in the task[] array * Return 0 if found, and 1 if not found. */int bad_task_ptr(struct task_struct *p)            //--檢查任務結構指標p{    int     i;    if (!p)        return 0;    for (i=0 ; i<NR_TASKS ; i++)        if (task[i] == p)            return 0;    return 1;}    /* * This routine scans the pid tree and make sure the rep invarient still * holds.  Used for debugging only, since it's very slow.... * * It looks a lot scarier than it really is.... we're doing **nothing more * than verifying the doubly-linked list found**in p_ysptr and p_osptr, * and checking it corresponds with the process tree defined by p_cptr and * p_pptr; */void audit_ptree()                        //--檢查進程樹,僅用於調試{    int    i;    for (i=1 ; i<NR_TASKS ; i++) {        if (!task[i])            continue;        if (bad_task_ptr(task[i]->p_pptr))            printk("Warning, pid %d's parent link is bad/n",                task[i]->pid);        if (bad_task_ptr(task[i]->p_cptr))            printk("Warning, pid %d's child link is bad/n",                task[i]->pid);        if (bad_task_ptr(task[i]->p_ysptr))            printk("Warning, pid %d's ys link is bad/n",                task[i]->pid);        if (bad_task_ptr(task[i]->p_osptr))            printk("Warning, pid %d's os link is bad/n",                task[i]->pid);        if (task[i]->p_pptr == task[i])            printk("Warning, pid %d parent link points to self/n");        if (task[i]->p_cptr == task[i])            printk("Warning, pid %d child link points to self/n");        if (task[i]->p_ysptr == task[i])            printk("Warning, pid %d ys link points to self/n");        if (task[i]->p_osptr == task[i])            printk("Warning, pid %d os link points to self/n");        if (task[i]->p_osptr) {            if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)                printk(            "Warning, pid %d older sibling %d parent is %d/n",                task[i]->pid, task[i]->p_osptr->pid,                task[i]->p_osptr->p_pptr->pid);            if (task[i]->p_osptr->p_ysptr != task[i])                printk(        "Warning, pid %d older sibling %d has mismatched ys link/n",                task[i]->pid, task[i]->p_osptr->pid);        }        if (task[i]->p_ysptr) {            if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)                printk(            "Warning, pid %d younger sibling %d parent is %d/n",                task[i]->pid, task[i]->p_osptr->pid,                task[i]->p_osptr->p_pptr->pid);            if (task[i]->p_ysptr->p_osptr != task[i])                printk(        "Warning, pid %d younger sibling %d has mismatched os link/n",                task[i]->pid, task[i]->p_ysptr->pid);        }        if (task[i]->p_cptr) {            if (task[i]->p_cptr->p_pptr != task[i])                printk(            "Warning, pid %d youngest child %d has mismatched parent link/n",                task[i]->pid, task[i]->p_cptr->pid);            if (task[i]->p_cptr->p_ysptr)                printk(            "Warning, pid %d youngest child %d has non-NULL ys link/n",                task[i]->pid, task[i]->p_cptr->pid);        }    }}#endif /* DEBUG_PROC_TREE */static inline int send_sig(long sig,struct task_struct * p,int priv){                                                        //--向指定任務發送訊號sig,許可權為priv    if (!p)        return -EINVAL;    if (!priv && (current->euid!=p->euid) && !suser())    //--檢查許可權,是否是目前使用者,是否是超級使用者        return -EPERM;    if ((sig == SIGKILL) || (sig == SIGCONT)) {            //--如果是sigkill和sigcout訊號,則...        if (p->state == TASK_STOPPED)            p->state = TASK_RUNNING;        p->exit_code = 0;        p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |                (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );    //--去掉可能會導致進程停止的訊號    }     /* If the signal will be ignored, don't even post it */    if ((int) p->sigaction[sig-1].sa_handler == 1)        //--如果訊號將被進程p忽略,則不用發送。        return 0;    /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */    if ((sig >= SIGSTOP) && (sig <= SIGTTOU))         p->signal &= ~(1<<(SIGCONT-1));    /* Actually deliver the signal */    p->signal |= (1<<(sig-1));                            //--向p發送訊號    return 0;}int session_of_pgrp(int pgrp)                            //--根據進程組號pgrp取得進程組所屬的會話號{    struct task_struct **p;     for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)        if ((*p)->pgrp == pgrp)            return((*p)->session);    return -1;}int kill_pg(int pgrp, int sig, int priv)                //--向進程組發送訊號{    struct task_struct **p;    int err,retval = -ESRCH;    int found = 0;    if (sig<1 || sig>32 || pgrp<=0)        return -EINVAL;     for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)        if ((*p)->pgrp == pgrp) {            if (sig && (err = send_sig(sig,*p,priv)))                retval = err;            else                found++;        }    return(found ? 0 : retval);}int kill_proc(int pid, int sig, int priv)                //--向進程發送訊號{     struct task_struct **p;    if (sig<1 || sig>32)        return -EINVAL;    for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)        if ((*p)->pid == pid)            return(sig ? send_sig(sig,*p,priv) : 0);    return(-ESRCH);}/* * POSIX specifies that kill(-1,sig) is unspecified, but what we have * is probably wrong.  Should make it like BSD or SYSV. */int sys_kill(int pid,int sig)                            //--用於向任何進程或進程組發送任何訊號{    struct task_struct **p = NR_TASKS + task;    int err, retval = 0;    if (!pid)                                            //--訊號發送給當前進程的進程組中所有的進程        return(kill_pg(current->pid,sig,0));    if (pid == -1) {                                    //--訊號發送給除初始進程外的所有進程        while (--p > &FIRST_TASK)            if (err = send_sig(sig,*p,0))                retval = err;        return(retval);    }    if (pid < 0)                                         //--訊號發送給進程組-pid的所有進程        return(kill_pg(-pid,sig,0));    /* Normal kill */    return(kill_proc(pid,sig,0));                        //--訊號發送給指定進程}/* * Determine if a process group is "orphaned", according to the POSIX * definition in 2.2.2.52.  Orphaned process groups are not to be affected * by terminal-generated stop signals.  Newly orphaned process groups are * to receive a SIGHUP and a SIGCONT. * * "I ask you, have you ever known what it is to be an orphan?" */int is_orphaned_pgrp(int pgrp)                            //--判斷一個進程是否是孤兒進程{                                                        //--如果...如果...否則...我也看不懂什麼是孤兒進程了    struct task_struct **p;    for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {        if (!(*p) ||            ((*p)->pgrp != pgrp) ||             ((*p)->state == TASK_ZOMBIE) ||            ((*p)->p_pptr->pid == 1))            continue;        if (((*p)->p_pptr->pgrp != pgrp) &&            ((*p)->p_pptr->session == (*p)->session))            return 0;    }    return(1);    /* (sighing) "Often!" */                //--為孤兒進程...}static int has_stopped_jobs(int pgrp)                    //--判斷進程組中是否有處於停止狀態的作業{    struct task_struct ** p;    for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {        if ((*p)->pgrp != pgrp)            continue;        if ((*p)->state == TASK_STOPPED)            return(1);    }    return(0);}volatile void do_exit(long code)                        //--程式退出處理函數{    struct task_struct *p;    int i;                                                         //--首先釋放當前進程程式碼片段和資料區段所佔的記憶體    free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));    free_page_tables(get_base(current->ldt[2]),get_limit(0x17));    for (i=0 ; i<NR_OPEN ; i++)                            //--關閉當前進程開啟著的所有檔案        if (current->filp[i])            sys_close(i);    iput(current->pwd);                                    //--目前的目錄    current->pwd = NULL;    iput(current->root);                                //--根目錄    current->root = NULL;    iput(current->executable);                            //--執行檔案    current->executable = NULL;    iput(current->library);                                //--庫檔案    current->library = NULL;    current->state = TASK_ZOMBIE;                        //--僵死狀態    current->exit_code = code;    /*      * Check to see if any process groups have become orphaned     * as a result of our exiting, and if they have any stopped     * jobs, send them a SIGUP and then a SIGCONT.  (POSIX 3.2.2.2)     *     * Case i: Our father is in a different pgrp than we are     * and we were the only connection outside, so our pgrp     * is about to become orphaned.      */                                                //--檢查當前進程的退出是否會造成進程組變成孤兒進程    if ((current->p_pptr->pgrp != current->pgrp) &&        (current->p_pptr->session == current->session) &&        is_orphaned_pgrp(current->pgrp) &&        has_stopped_jobs(current->pgrp)) {        kill_pg(current->pgrp,SIGHUP,1);        kill_pg(current->pgrp,SIGCONT,1);    }    /* Let father know we died */    current->p_pptr->signal |= (1<<(SIGCHLD-1));    //--發送訊號通知父進程當前進程將終止        /*     * This loop does two things:     *        * A.  Make init inherit all the child processes     * B.  Check to see if any process groups have become orphaned     *    as a result of our exiting, and if they have any stopped     *    jons, send them a SIGUP and then a SIGCONT.  (POSIX 3.2.2.2)     */    if (p = current->p_cptr) {                        //--讓init進程成為其所有子進程的父進程        while (1) {            p->p_pptr = task[1];            if (p->state == TASK_ZOMBIE)            //--若為僵死狀態,則向init發送進程已終止訊號                task[1]->signal |= (1<<(SIGCHLD-1));            /*             * process group orphan check             * Case ii: Our child is in a different pgrp              * than we are, and it was the only connection             * outside, so the child pgrp is now orphaned.             */            if ((p->pgrp != current->pgrp) &&        //--呃...好複雜                (p->session == current->session) &&    //--處理兄弟進程                is_orphaned_pgrp(p->pgrp) &&                has_stopped_jobs(p->pgrp)) {                kill_pg(p->pgrp,SIGHUP,1);                kill_pg(p->pgrp,SIGCONT,1);            }            if (p->p_osptr) {                p = p->p_osptr;                continue;            }            /*             * This is it; link everything into init's children              * and leave              */            p->p_osptr = task[1]->p_cptr;            //--最老與最新子進程的處理            task[1]->p_cptr->p_ysptr = p;            task[1]->p_cptr = current->p_cptr;            current->p_cptr = 0;            break;        }    }    if (current->leader) {                            //--如果當前進程為會話頭領進程        struct task_struct **p;        struct tty_struct *tty;        if (current->tty >= 0) {            tty = TTY_TABLE(current->tty);            if (tty->pgrp>0)                kill_pg(tty->pgrp, SIGHUP, 1);            tty->pgrp = 0;            tty->session = 0;        }         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)            if ((*p)->session == current->session)                (*p)->tty = -1;    }    if (last_task_used_math == current)                //--如果當前進程上次使用國副處理器,則...        last_task_used_math = NULL;#ifdef DEBUG_PROC_TREE    audit_ptree();                                    //--調用進程樹檢測顯示函數#endif    schedule();                                        //--重新調度}int sys_exit(int error_code)                        //--終止進程{    do_exit((error_code&0xff)<<8);}int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options){                                                    //--系統調用,掛起當前進程,直到pid指定的子進程退出    int flag;    struct task_struct *p;    unsigned long oldblocked;    verify_area(stat_addr,4);                        //--檢測記憶體空間是否足夠repeat:    flag=0;                                            //--從當前進程的最年輕子進程開始掃描子進程兄弟鏈表    for (p = current->p_cptr ; p ; p = p->p_osptr) {        if (pid>0) {            if (p->pid != pid)                continue;        } else if (!pid) {            if (p->pgrp != current->pgrp)                continue;        } else if (pid != -1) {            if (p->pgrp != -pid)                continue;        }        switch (p->state) {                            //--如果...如果...處理...            case TASK_STOPPED:                if (!(options & WUNTRACED) ||                     !p->exit_code)                    continue;                put_fs_long((p->exit_code << 8) | 0x7f,                    stat_addr);                p->exit_code = 0;                return p->pid;            case TASK_ZOMBIE:                current->cutime += p->utime;                current->cstime += p->stime;                flag = p->pid;                put_fs_long(p->exit_code, stat_addr);                release(p);#ifdef DEBUG_PROC_TREE                audit_ptree();#endif                return flag;            default:                flag=1;                continue;        }    }    if (flag) {        if (options & WNOHANG)            return 0;        current->state=TASK_INTERRUPTIBLE;        oldblocked = current->blocked;        current->blocked &= ~(1<<(SIGCHLD-1));        schedule();        current->blocked = oldblocked;        if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))            return -ERESTARTSYS;        else            goto repeat;    }    return -ECHILD;}|xGv00|fcc8d4de8197f69fde70263fb4d52380

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.