免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
網(wǎng)易博客歡迎您

 unsigned long stack_size,  int __user *parent_tidptr,  int __user *child_tidptr)

{       

        struct task_struct *p;

        int trace = 0;

        long nr;

如果創(chuàng)建新的user namespace就需要具備管理員權(quán)限或者CAP_SETUID或者CAP_SETGID。

        if (clone_flags & CLONE_NEWUSER) {

                if (clone_flags & CLONE_THREAD)

                        return -EINVAL;

                if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) ||

                                !capable(CAP_SETGID))

                        return -EPERM;

        }

檢查是否跟蹤子進(jìn)程,如果是,就根據(jù)不同的跟蹤行為發(fā)送不同的跟蹤事件。

PTRACE_EVENT_VFORK: 使子進(jìn)程下次調(diào)用 vfork() 時(shí)停止其執(zhí)行,并自動(dòng)跟蹤開(kāi)始執(zhí)行時(shí)就已設(shè)置 SIGSTOP 信號(hào)的新進(jìn)程。

PTRACE_EVENT_CLONE:  使子進(jìn)程下次調(diào)用 clone() 時(shí)停止其執(zhí)行,并自動(dòng)跟蹤開(kāi)始執(zhí)行時(shí)就已設(shè)置 SIGSTOP 信號(hào)的新進(jìn)程。

PTRACE_EVENT_FORK: 使子進(jìn)程下次調(diào)用 fork() 時(shí)停止其執(zhí)行,并自動(dòng)跟蹤開(kāi)始執(zhí)行時(shí)就已設(shè)置 SIGSTOP 信號(hào)的新進(jìn)程。

        if (likely(user_mode(regs)) && !(clone_flags & CLONE_UNTRACED)) {

                if (clone_flags & CLONE_VFORK)

                        trace = PTRACE_EVENT_VFORK;

                else if ((clone_flags & CSIGNAL) != SIGCHLD)

                        trace = PTRACE_EVENT_CLONE;

                else

                        trace = PTRACE_EVENT_FORK;

                if (likely(!ptrace_event_enabled(current, trace)))

                        trace = 0;

        }

分配進(jìn)程描述符task_struct和內(nèi)核堆??臻g,通過(guò)父進(jìn)程的相關(guān)信息初始化一些資源。這個(gè)函數(shù)在進(jìn)程創(chuàng)建中做了很多重要工作后面將詳細(xì)講述。

        p = copy_process(clone_flags, stack_start, regs, stack_size,child_tidptr, NULL, trace);

        if (!IS_ERR(p)) {

                struct completion vfork;

獲取在當(dāng)前進(jìn)程的PID命名空間中的id號(hào)。

                nr = task_pid_vnr(p);

                if (clone_flags & CLONE_PARENT_SETTID)

                        put_user(nr, parent_tidptr);

如果是通過(guò)vfork創(chuàng)建進(jìn)程則初始化完成量vfork,它保證了子進(jìn)程先運(yùn)行。

                if (clone_flags & CLONE_VFORK) {

                        p->vfork_done = &vfork;

                        init_completion(&vfork);

                        get_task_struct(p);

                }

將新進(jìn)程插入調(diào)度隊(duì)列,等待調(diào)度運(yùn)行。后面詳細(xì)分析。

                wake_up_new_task(p);

發(fā)送跟蹤事件

                if (unlikely(trace))

                        ptrace_event(trace, nr);

如果是通過(guò)vfork創(chuàng)建進(jìn)程則掛起當(dāng)前進(jìn)程等待子進(jìn)程運(yùn)行結(jié)束后再運(yùn)行。

                if (clone_flags & CLONE_VFORK) {

                        if (!wait_for_vfork_done(p, &vfork))

                                ptrace_event(PTRACE_EVENT_VFORK_DONE, nr);

                }

        } else {

                nr = PTR_ERR(p);

        }

返回到發(fā)出創(chuàng)建新進(jìn)程系統(tǒng)調(diào)用的進(jìn)程中。如fork系統(tǒng)調(diào)用會(huì)兩次返回,一次返回到父進(jìn)程,返回值為子進(jìn)程的進(jìn)程id,另一次返回到子進(jìn)程,后面會(huì)講到返回到子進(jìn)程的情況。

        return nr;

}

上面有一些函數(shù)需要進(jìn)一步分析如下:

【do_fork--->copy_process】

static struct task_struct *copy_process(unsigned long clone_flags,unsigned long stack_start,

struct pt_regs *regs,unsigned long stack_size, int __user *child_tidptr,struct pid *pid, int trace)

{

        int retval;

        struct task_struct *p;

        int cgroup_callbacks_done = 0;

如果創(chuàng)建新的命名空間就不能同時(shí)又拷貝父進(jìn)程的文件系統(tǒng)信息。

        if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))

                return ERR_PTR(-EINVAL);

同一線程組中的進(jìn)程必須共享信號(hào)

        if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))

                return ERR_PTR(-EINVAL);

共享信號(hào)處理方法就必須共享用戶虛擬空間

        if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))

                return ERR_PTR(-EINVAL);

        if ((clone_flags & CLONE_PARENT) &&

                                current->signal->flags & SIGNAL_UNKILLABLE)

                return ERR_PTR(-EINVAL);

執(zhí)行附加的安全檢查。

        retval = security_task_create(clone_flags);

        if (retval)

                goto fork_out;

        retval = -ENOMEM;

函數(shù)dup_task_struct要做的就是下面幾件事:

tsk = alloc_task_struct_node(node); 為新進(jìn)程分配一個(gè)task_struct結(jié)構(gòu)

ti = alloc_thread_info_node(tsk, node); 分配2頁(yè)的內(nèi)核棧空間并返回頁(yè)地址

err = arch_dup_task_struct(tsk, orig); 將父進(jìn)程的進(jìn)程描述符結(jié)構(gòu)task_struct的內(nèi)容拷貝到子進(jìn)程的進(jìn)程描述符結(jié)構(gòu)task_struct中

tsk->stack = ti;線程描述符結(jié)構(gòu)thread_info存放在上面分配的兩頁(yè)??臻g的開(kāi)始出,讓tsk->stack指向線程描述符結(jié)構(gòu)。

setup_thread_stack(tsk, orig);將父進(jìn)程的線程描述符結(jié)構(gòu)內(nèi)容拷貝到子進(jìn)程中。

        p = dup_task_struct(current);

        if (!p)

                goto fork_out;

......

        retval = -EAGAIN;

每個(gè)進(jìn)程都屬于某個(gè)用戶,每個(gè)用戶都有它的資源限制,所以一個(gè)用戶所能創(chuàng)建的進(jìn)程數(shù)不能超過(guò)他的限制,除非他具有管理員權(quán)限。

        if (atomic_read(&p->real_cred->user->processes) >=

                        task_rlimit(p, RLIMIT_NPROC)) {

                if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&

                    p->real_cred->user != INIT_USER)

                        goto bad_fork_free;

        }

        current->flags &= ~PF_NPROC_EXCEEDED;

結(jié)構(gòu)體struct cred包含了uid、gid、user等安全權(quán)能相關(guān)的東西。在函數(shù)copy_creds中先判斷是不是創(chuàng)建線程CLONE_THREAD,如果是就共享父進(jìn)程的cred結(jié)構(gòu),如果不是就重新分配一個(gè)cred結(jié)構(gòu),并用父進(jìn)程中cred的內(nèi)容拷貝到新分配的cred中。

        retval = copy_creds(p, clone_flags);

        if (retval < 0)

                goto bad_fork_free;

        retval = -EAGAIN;

檢查系統(tǒng)中的進(jìn)程數(shù)量是否超過(guò)max_threads。這個(gè)變量的缺省值取決于系統(tǒng)內(nèi)存容量。

        if (nr_threads >= max_threads)

                goto bad_fork_cleanup_count;

如果實(shí)現(xiàn)新的進(jìn)程的執(zhí)行腳本執(zhí)行域和可執(zhí)行格式的內(nèi)核函數(shù)都包含在內(nèi)核模塊中,則遞增它們的使用計(jì)數(shù)器。

        if (!try_module_get(task_thread_info(p)->exec_domain->module))

                goto bad_fork_cleanup_count;

did_exec記錄了進(jìn)程發(fā)出execve調(diào)用的次數(shù) 

        p->did_exec = 0;

        ......

函數(shù)sched_fork中初始化了調(diào)度實(shí)體結(jié)構(gòu)struct sched_entity se;,設(shè)置了進(jìn)程優(yōu)先級(jí),設(shè)置了進(jìn)程調(diào)度類(lèi),該函數(shù)后面詳細(xì)講解。 

        sched_fork(p);

        retval = perf_event_init_task(p);

        if (retval)

                goto bad_fork_cleanup_policy;

        retval = audit_alloc(p);

        if (retval)

                goto bad_fork_cleanup_policy;

        如果設(shè)置了COPY_SYSVSEM,則使用父進(jìn)程的System V信號(hào)量。

        retval = copy_semundo(clone_flags, p);

        if (retval)

                goto bad_fork_cleanup_audit;

如果CLONE_FILES置位,則使用父進(jìn)程的文件描述符列表,否則創(chuàng)建新的文件描述符列表,并將父進(jìn)程的文件描述符列表拷到新的列表中。

        retval = copy_files(clone_flags, p);

        if (retval)

                goto bad_fork_cleanup_semundo;

如果CLONE_FS置位,則使用父進(jìn)程的文件系統(tǒng)上下文,否者創(chuàng)建自己的 struct fs_struct結(jié)構(gòu)并用父進(jìn)程的 struct fs_struct初始化新的 struct fs_struct。該結(jié)構(gòu)中包含根目錄、當(dāng)前工作目錄等。

        retval = copy_fs(clone_flags, p);

        if (retval)

                goto bad_fork_cleanup_files;

        retval = copy_sighand(clone_flags, p);

        if (retval)

                goto bad_fork_cleanup_fs;

如果CLONE_SIGHAND置位,則使用父進(jìn)程的信號(hào)處理程序,否則創(chuàng)建新的sighand_struct,并將父進(jìn)程的信號(hào)處理結(jié)構(gòu)內(nèi)容拷到新的列信號(hào)處理結(jié)構(gòu)中。

        retval = copy_signal(clone_flags, p);

        if (retval)

                goto bad_fork_cleanup_sighand;

如果CLONE_VM置位,則共享父進(jìn)程的地址空間,兩個(gè)進(jìn)程共用同一mm_struct結(jié)構(gòu),否者創(chuàng)建一個(gè)父進(jìn)程的頁(yè)表副本但不復(fù)制頁(yè)的實(shí)際內(nèi)容,而是使用寫(xiě)時(shí)復(fù)制機(jī)制。

        retval = copy_mm(clone_flags, p);

        if (retval)

                goto bad_fork_cleanup_signal;

共享父進(jìn)程的命名空間或是建立新的命名空間。下面對(duì)命名空間的做一點(diǎn)說(shuō)明:

將子系統(tǒng)的全局屬性封裝到命名空間中,每個(gè)進(jìn)程關(guān)聯(lián)到一個(gè)選定的命名空間。每個(gè)可以感知命名空間的子系統(tǒng)都必須提供一個(gè)數(shù)據(jù)結(jié)構(gòu),將所有通過(guò)命名空間形式提供的對(duì)象集中起來(lái)。struct nsproxy 用于匯集指向特定于子系統(tǒng)的命名空間包裝的指針:

struct nsproxy {

        atomic_t count;

        struct uts_namespace *uts_ns; 包含內(nèi)核的名稱、版本、底層體系結(jié)構(gòu)類(lèi)型等信息

        struct ipc_namespace *ipc_ns;進(jìn)程間通信的IPC有關(guān)信息。

        struct mnt_namespace *mnt_ns;已經(jīng)裝載的文件系統(tǒng)的視圖。

        struct pid_namespace *pid_ns;有關(guān)進(jìn)程ID的信息

        struct net           *net_ns;半酣所有網(wǎng)絡(luò)相關(guān)的命名空間參數(shù)

};

與上面命名空間相對(duì)應(yīng)的幾個(gè)標(biāo)志:

CLONE_NEWUTS:創(chuàng)建新的utsname組 

CLONE_NEWIPC :創(chuàng)建新的IPC命名空間

CLONE_NEWUSER:創(chuàng)建新的用戶命名空間

 CLONE_NEWPID:創(chuàng)建新的PID命名空間

CLONE_NEWNET:創(chuàng)建新的網(wǎng)絡(luò)命名空間

        retval = copy_namespaces(clone_flags, p);

        if (retval)

                goto bad_fork_cleanup_mm;

        retval = copy_io(clone_flags, p);

        if (retval)

                goto bad_fork_cleanup_namespaces;

復(fù)制進(jìn)程中特定于線程的數(shù)據(jù)并且讓CPU上下文中的pc字段指向函數(shù)ret_from_fork,該函數(shù)用匯編實(shí)現(xiàn),fork調(diào)用就是通過(guò)它返回到子進(jìn)程中的。

        retval = copy_thread(clone_flags, stack_start, stack_size, p, regs);

        if (retval)

                goto bad_fork_cleanup_io;

為進(jìn)城分配pid,下面函數(shù)做了很多處理,將在后面分析。

        if (pid != &init_struct_pid) {

                retval = -ENOMEM;

                pid = alloc_pid(p->nsproxy->pid_ns);

                if (!pid)

                        goto bad_fork_cleanup_io;

        }

字段p->pid中保存的是進(jìn)程全局pid,所以它的pid應(yīng)當(dāng)從最頂層命名空間中獲取,nr = pid->numbers[0].nr;(每一個(gè)進(jìn)程在它之上的每一級(jí)命名空間中都有一個(gè)id)。

        p->pid = pid_nr(pid);

        p->tgid = p->pid;

如果創(chuàng)建的是線程,則它的線程組id于當(dāng)前進(jìn)程的線程組id相同

        if (clone_flags & CLONE_THREAD)

                p->tgid = current->tgid;

        p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;

        p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;

......

        if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM)

......

    如果創(chuàng)建線程就將 p->exit_signal設(shè)為-1,因?yàn)橹挥挟?dāng)線程組的最后一個(gè)成員死亡才會(huì)產(chǎn)生一個(gè)信號(hào)已通知線程組首領(lǐng)進(jìn)程的父進(jìn)程。

   if (clone_flags & CLONE_THREAD)

                p->exit_signal = -1;

        else if (clone_flags & CLONE_PARENT)

                p->exit_signal = current->group_leader->exit_signal;

        else

                p->exit_signal = (clone_flags & CSIGNAL);

......

        p->group_leader = p;

        INIT_LIST_HEAD(&p->thread_group);

        INIT_HLIST_HEAD(&p->task_works);

        cgroup_fork_callbacks(p);

        cgroup_callbacks_done = 1;

        write_lock_irq(&tasklist_lock);

如果創(chuàng)建線程,新進(jìn)程與當(dāng)前進(jìn)程有相同的父進(jìn)程,否則當(dāng)前進(jìn)程就是新進(jìn)程的父進(jìn)程。

        if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {

                p->real_parent = current->real_parent;

                p->parent_exec_id = current->parent_exec_id;

        } else {

                p->real_parent = current;

                p->parent_exec_id = current->self_exec_id;

        }

        spin_lock(¤t->sighand->siglock);

        recalc_sigpending();

如果當(dāng)前進(jìn)程還有未決信號(hào)就錯(cuò)誤返回。

        if (signal_pending(current)) {

                spin_unlock(¤t->sighand->siglock);

                write_unlock_irq(&tasklist_lock);

                retval = -ERESTARTNOINTR;

                goto bad_fork_free_pid;

        }

如果創(chuàng)建進(jìn)程就將線程數(shù)遞增1,并且讓新進(jìn)程與當(dāng)前進(jìn)程有相同的組長(zhǎng)進(jìn)程

        if (clone_flags & CLONE_THREAD) {

                current->signal->nr_threads++;

                atomic_inc(¤t->signal->live);

                atomic_inc(¤t->signal->sigcnt);

                p->group_leader = current->group_leader;

                list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);

        }

        if (likely(p->pid)) {

                ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);

如果新進(jìn)程是線程組組長(zhǎng)進(jìn)程,就進(jìn)入下面分支

                if (thread_group_leader(p)) {

                        if (is_child_reaper(pid))

                                p->nsproxy->pid_ns->child_reaper = p;

將當(dāng)前進(jìn)程組進(jìn)程的組id和會(huì)話id掛到新進(jìn)程哈希數(shù)組task->pids[]中對(duì)應(yīng)位置。

                        p->signal->leader_pid = pid;

                        p->signal->tty = tty_kref_get(current->signal->tty);

                        attach_pid(p, PIDTYPE_PGID, task_pgrp(current));

                        attach_pid(p, PIDTYPE_SID, task_session(current));

                        list_add_tail(&p->sibling, &p->real_parent->children);

                        list_add_tail_rcu(&p->tasks, &init_task.tasks);

                        __this_cpu_inc(process_counts);

                }

將新的pid結(jié)構(gòu)掛到新進(jìn)程哈希數(shù)組task->pids[]中對(duì)應(yīng)位置。

                attach_pid(p, PIDTYPE_PID, pid);

新進(jìn)程加入進(jìn)程集合,遞增nr_threads。

                nr_threads++;

        }

變量total_forks記錄被創(chuàng)建進(jìn)程的數(shù)量

        total_forks++;

        return p;

......

}

【do_fork--->copy_process--->sched_fork】

void sched_fork(struct task_struct *p)

{

        unsigned long flags;

        int cpu = get_cpu();

初始化進(jìn)程調(diào)度實(shí)體se的相關(guān)成員

        __sched_fork(p);

將進(jìn)程狀態(tài)置于運(yùn)行狀態(tài)

        p->state = TASK_RUNNING;

新進(jìn)程的優(yōu)先級(jí)繼承于父進(jìn)程的普通優(yōu)先級(jí)。對(duì)于優(yōu)先級(jí)做一下說(shuō)明,進(jìn)程有三個(gè)優(yōu)先級(jí):static_prio:靜態(tài)優(yōu)先級(jí)是進(jìn)程啟動(dòng)時(shí)分配的優(yōu)先級(jí)。它可以用nice系統(tǒng)調(diào)用修改。

normal_prio:基于進(jìn)程的靜態(tài)優(yōu)先級(jí)和調(diào)度策略計(jì)算出來(lái)的優(yōu)先級(jí),調(diào)度策略也可以通過(guò)系 統(tǒng)調(diào)用改變,所以即使靜態(tài)優(yōu)先級(jí)相同,普通優(yōu)先級(jí)也可能不同。

prio:在某些情況下內(nèi)核需要暫時(shí)提高進(jìn)程的優(yōu)先級(jí),所以就需要第三個(gè)成員來(lái)表示。調(diào)度 器算法中要考慮的優(yōu)先級(jí)就保存在prio。

        p->prio = current->normal_prio;

sched_reset_on_fork用于判斷是否恢復(fù)默認(rèn)的優(yōu)先級(jí)或調(diào)度策略。

        if (unlikely(p->sched_reset_on_fork)) {

                if (task_has_rt_policy(p)) {

                        p->policy = SCHED_NORMAL;

                        p->static_prio = NICE_TO_PRIO(0);

                        p->rt_priority = 0;

                } else if (PRIO_TO_NICE(p->static_prio) < 0)

                        p->static_prio = NICE_TO_PRIO(0);

                p->prio = p->normal_prio = __normal_prio(p);

設(shè)置進(jìn)程權(quán)重,關(guān)于權(quán)重的問(wèn)題后面會(huì)講解。

                set_load_weight(p);

                p->sched_reset_on_fork = 0;

        }

如果不是事實(shí)進(jìn)程,就設(shè)置調(diào)度類(lèi)為完全公平調(diào)度類(lèi)

        if (!rt_prio(p->prio))

                p->sched_class = &fair_sched_class;

        if (p->sched_class->task_fork)

                p->sched_class->task_fork(p);

        raw_spin_lock_irqsave(&p->pi_lock, flags);

設(shè)置進(jìn)程在那個(gè)cpu上運(yùn)行;

        set_task_cpu(p, cpu);

        raw_spin_unlock_irqrestore(&p->pi_lock, flags);

......

}

【do_fork--->copy_process--->alloc_pid】

struct pid *alloc_pid(struct pid_namespace *ns)

{

        struct pid *pid;

        enum pid_type type;

        int i, nr;

        struct pid_namespace *tmp;

        struct upid *upid;

 分配一個(gè)pid結(jié)構(gòu),一個(gè)進(jìn)程對(duì)應(yīng)著一個(gè)這樣的結(jié)構(gòu),該結(jié)構(gòu)用于內(nèi)核空間對(duì)進(jìn)程的管理

        pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);

PID命名空間結(jié)構(gòu)中有一個(gè)位圖pid_ns->pidmap[],每一個(gè)位就表示在該命名空間中的一個(gè)

進(jìn)程號(hào),如果該位位1表示該位對(duì)應(yīng)的進(jìn)程號(hào)已經(jīng)被分配。所以在該命名空間分配進(jìn)程號(hào)就是在位圖中找第一個(gè)為0的位。ns->level表示該命名空間所在的層次,其值越小表示層次越高。上面提到pid結(jié)構(gòu)是內(nèi)核對(duì)進(jìn)程管理的結(jié)構(gòu),upid就對(duì)應(yīng)著用戶空間的進(jìn)程號(hào)。進(jìn)程PID命名空間可能有很多層次,每一個(gè)層次中就對(duì)應(yīng)著一個(gè)這樣的結(jié)構(gòu),所以新進(jìn)程建立是要為它在它本命名空間和上層所有命名空間中分配一個(gè)id。

        tmp = ns;

        for (i = ns->level; i >= 0; i--) {

                nr = alloc_pidmap(tmp);

                if (nr < 0)

                        goto out_free;

                pid->numbers[i].nr = nr;

                pid->numbers[i].ns = tmp;

                tmp = tmp->parent;

        }

獲取新進(jìn)程的命名空間。

        get_pid_ns(ns);

        pid->level = ns->level;

        atomic_set(&pid->count, 1);

        for (type = 0; type < PIDTYPE_MAX; ++type)

                INIT_HLIST_HEAD(&pid->tasks[type]);

        upid = pid->numbers + ns->level;

        spin_lock_irq(&pidmap_lock);

將進(jìn)程的所有upid結(jié)構(gòu)都置于pid哈希表中。

        for ( ; upid >= pid->numbers; --upid)

                hlist_add_head_rcu(&upid->pid_chain,

                                &pid_hash[pid_hashfn(upid->nr, upid->ns)]);

        spin_unlock_irq(&pidmap_lock);

......

}

【do_fork--->wake_up_new_task】

void wake_up_new_task(struct task_struct *p)

{

#ifdef CONFIG_SMP

設(shè)置進(jìn)程的調(diào)度隊(duì)列完全公平調(diào)度隊(duì)列p->se.cfs_rq或者實(shí)時(shí)調(diào)度隊(duì)列p->rt.rt_rq。

        set_task_cpu(p, select_task_rq(p, SD_BALANCE_FORK, 0));

#endif

rq指向就緒隊(duì)列,每個(gè)CPU只有一個(gè)這樣的隊(duì)列,所有將要在該CPU上運(yùn)行等待調(diào)度的進(jìn)程都在該隊(duì)列中。

        rq = __task_rq_lock(p);

函數(shù)activate_task將新進(jìn)程插入隊(duì)列中p->sched_class->enqueue_task(rq, p, flags);等待調(diào)度,該函數(shù)特定于調(diào)度類(lèi),后面講解調(diào)度算法時(shí)講解。

        activate_task(rq, p, 0);

現(xiàn)在進(jìn)程已經(jīng)在隊(duì)列中了。

        p->on_rq = 1;

        trace_sched_wakeup_new(p, true);

用一個(gè)新?lián)Q新的進(jìn)程來(lái)?yè)屨籍?dāng)前進(jìn)程,當(dāng)然,能否搶占得了,還得看其優(yōu)先級(jí)等相關(guān)參數(shù)。

        check_preempt_curr(rq, p, WF_FORK);

#ifdef CONFIG_SMP

        if (p->sched_class->task_woken)

                p->sched_class->task_woken(rq, p);

#endif

        task_rq_unlock(rq, p, &flags);

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Linux fork的內(nèi)核實(shí)現(xiàn)
淺談Linux內(nèi)核創(chuàng)建新進(jìn)程的全過(guò)程
通過(guò)代碼分析微內(nèi)核與宏內(nèi)核
linux 系統(tǒng)調(diào)用fork vfork clone
深入理解Linux進(jìn)程管理
linux內(nèi)核分析筆記----進(jìn)程管理
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服