乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      網(wǎng)易博客歡迎您

       老匹夫 2014-09-12

       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)跟蹤開始執(zhí)行時(shí)就已設(shè)置 SIGSTOP 信號(hào)的新進(jìn)程。

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

      PTRACE_EVENT_FORK: 使子進(jìn)程下次調(diào)用 fork() 時(shí)停止其執(zhí)行,并自動(dòng)跟蹤開始執(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,通過父進(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);

      如果是通過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);

      如果是通過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頁的內(nèi)核??臻g并返回頁地址

      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存放在上面分配的兩頁棧空間的開始出,讓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ù)不能超過他的限制,除非他具有管理員權(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ù)量是否超過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)度類,該函數(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)程的頁表副本但不復(fù)制頁的實(shí)際內(nèi)容,而是使用寫時(shí)復(fù)制機(jī)制。

              retval = copy_mm(clone_flags, p);

              if (retval)

                      goto bad_fork_cleanup_signal;

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

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

      struct nsproxy {

              atomic_t count;

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

              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)用就是通過它返回到子進(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)程有相同的組長進(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)程是線程組組長進(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í)做一下說明,進(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ì)算出來的優(yōu)先級(jí),調(diào)度策略也可以通過系 統(tǒng)調(diào)用改變,所以即使靜態(tài)優(yōu)先級(jí)相同,普通優(yōu)先級(jí)也可能不同。

      prio:在某些情況下內(nèi)核需要暫時(shí)提高進(jìn)程的優(yōu)先級(jí),所以就需要第三個(gè)成員來表示。調(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)重的問題后面會(huì)講解。

                      set_load_weight(p);

                      p->sched_reset_on_fork = 0;

              }

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

              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)度類,后面講解調(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)程來搶占當(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);

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多