linux内核设计与实现-第3章 进程管理

第3章 进程管理

  • 3.2 进程描述符及任务结构

内核把进程的列表存放在叫做任务队列(task list)的双向循环链表中。32位机器,大约有1.7KB

链表的每一项都是类型为task_struct、称为进程描述符(process descriptor)的结构。

该结构定义在<linux/sched.h>文件中。进程描述符中包含一个具体进程的所有信息。

  • 3.2.1 分配进程描述符

#include <asm/thread_info.h>
x86体系
struct thread_info {
    struct task_struct *task;
    struct exec_domain *exec_domain;
    __u32 flags;
    __u32 status;
    __u32 cpu;
    int preempt_count;
    mm_segment_t addr_limit;
    struct restart_block restart_block;
    void *sysenter_return;
    int uaccess_err;
}
  • 3.2.2 进程描述符的存放

#include <linux/thread.h>

PID 最大值位32768 (short int 短整型的最大值)

可以通过修改/proc/sys/kernel/pid_max 来提高上限。

current_thread_info()->task;
  • 3.2.3 进程状态

 

进程状态

描述

TASK_RUNNING

运行

TASK_INTERRUPTIBLE

可中断

TASK_UNINTERRUPTIBLE

不可中断

__TATSK_TRACED

被其他进程跟踪的进程

__TASK_STOPPED

停止

  • 3.2.4 设置当前进程状态

#include <linux/sched.h>

set_task_state(task,state);

set_current_state(state);
  • 3.3.1 写时拷贝

Linux的fork() 使用写时拷贝(copy-on-write)页实现

  • 3.3.2 fork()

Linux 通过clone() 系统调用实现fork().

  • 3.4 线程在Linux中的实现

  • 3.4.1 创建线程

线程创建和普通进程的创建类似,只不过在调用clone() 的时候要传递一些参数标志来指明需要共享的资源

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

clone(SIGCHLD,0); //普通的fork()

clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0); // vfork() 的实现

 

clone() 参数标志 <linux/sched.h>

参数标志

含义

CLONE_FILES

父子进程共享打开的文件

CLONE_FS

父子系统共享文件系统信息

CLONE_IDLETASK

将PID设置为0,(只提供idle进程使用)

CLONE_NEWNS

为子进程创建新的命名空间

CLONE_PARENT

指定子进程与父进程拥有同一个父进程

CLONE_PTRACE

继续调试子进程

CLONE_SETTID

将TID回写至用户空间

CLONE_SETTLS

为子进程创建新的TLS

CLONE_SIGHAND

父进程共享信号处理函数及被阻断的信号

CLONE_SYSVSEM

父子进程共享System V SEM_UNDO 语义

CLONE_THREAD

父子进程放入相同的线程组

CLONE_VFORK

调用vfork(),所以父进程准备睡眠等待子进程将其唤醒

CLONE_UNTRACED

防止跟踪进程在子进程上强制执行CLONE_PTRACE

CLONE_STOP

以TASK_STOPPED状态开始进程

CLONE_SETTLS

为子进程创建新的TLS(thread-local storage)

CLONE_CHILD_CLEARTID

清除子进程的TID

CLONE_CHILD_SETTID

设置子进程的TID

CLONE_PARENT_SETTID

设置父进程的TID

CLONE_VM

父子进程共享地址空间

3.4.2 内核线程

# include <linux/kthread.h>
// 创建内核线程
struct task_struct *kthread_create(int (*threadfn)(void *data),void *data,const char namefmt[]...)

//新创建的进程处于不可运行状态,如果不通过调用wake_up_process()明确的唤醒它,它不会主动运行。

可以通过调用kthread_run()来达到。

struct task_struct *kthread_run(int (*threadfn)(void *data), void *data, const char namefmt[], ...)
// *kthread_run以宏实现的

#define kthread_run(threadfn,data,namefmt,....)                \
({                                                             \
    struct task_struct *k;                                     \
    k = thread_create(threadfn, data, namefmt, ## __VA_args___;\
    if (!IS_ERR(k))                                            \
        wake_up_process(k);                                    \
    k;                                                         \
})     

 

posted @ 2020-02-28 16:35  my_flash  阅读(41)  评论(0)    收藏  举报