当前位置:实例文章 » 其他实例» [文章]Linux进程控制(一)---进程创建和终止(写时拷贝,exit与_exit等)

Linux进程控制(一)---进程创建和终止(写时拷贝,exit与_exit等)

发布人:shili8 发布时间:2025-01-17 22:00 阅读次数:0

**Linux 进程控制 (一) --- 进程创建和终止**

在 Linux 中,进程是计算机系统中最基本的执行单元。每个进程都有自己的虚拟地址空间、进程描述符等信息。在本文中,我们将讨论 Linux 进程的创建和终止过程。

###1. 进程创建Linux 中进程的创建主要通过 `fork()` 系统调用实现。`fork()` 的作用是创建一个新进程,新进程与父进程共享同样的虚拟地址空间。

####1.1 fork() 系统调用`fork()` 系统调用的实现如下:

c// sys_fork.cSYSCALL_DEFINE0(fork)
{
 struct task_struct *tsk;
 unsigned long clone_flags = SIGCHLD;

 tsk = copy_process(current->mm, NULL, clone_flags, NULL, NULL,
 current->pid,0, NULL);
 if (!tsk) {
 return -EAGAIN;
 }

 if (clone_flags & CLONE_VM)
 tsk->mm = current->mm;

 return0;
}


在 `fork()` 系统调用中,我们首先通过 `copy_process()` 函数创建一个新进程。`copy_process()` 函数负责复制父进程的虚拟地址空间、进程描述符等信息。

####1.2 copy_process() 函数`copy_process()` 函数的实现如下:

c// mm/mmap.cstruct task_struct *copy_process(struct mm_struct *mm, struct pt_regs *regs,
 int clone_flags, unsigned long stack_start,
 const char __user *stack_ptr, pid_t pid,
 int nr, struct pt_regs *child_regs)
{
 struct task_struct *tsk;
 struct mm_struct *new_mm;

 tsk = kmem_cache_alloc(task_cachep, GFP_KERNEL);
 if (!tsk) {
 return NULL;
 }

 new_mm = copy_mm(tsk->mm, clone_flags & CLONE_VM ? tsk->mm : NULL,
 stack_start, stack_ptr);

 if (IS_ERR(new_mm)) {
 kmem_cache_free(task_cachep, tsk);
 return NULL;
 }

 tsk->stack_canary = get_random_int();
 tsk->pid = pid;
 tsk->nr = nr;

 if (clone_flags & CLONE_VM)
 tsk->mm = new_mm;

 return tsk;
}


在 `copy_process()` 函数中,我们首先通过 `kmem_cache_alloc()` 函数分配一个新的进程描述符。然后我们通过 `copy_mm()` 函数复制父进程的虚拟地址空间。

####1.3 exit() 系统调用`exit()` 系统调用的实现如下:

c// sys_exit.cSYSCALL_DEFINE0(exit)
{
 struct task_struct *tsk = current;

 if (unlikely(!tsk))
 return -ESRCH;

 tsk->exit_code =0;
 exit_mm(tsk);
 kthread_stop(tsk);
 kmem_cache_free(task_cachep, tsk);

 return0;
}


在 `exit()` 系统调用中,我们首先通过 `current` 变量获取当前进程的描述符。然后我们设置进程的退出代码为0,释放其虚拟地址空间,并停止其线程。

###2. 进程终止Linux 中进程的终止主要通过 `exit()` 系统调用实现。在上一节中,我们已经讨论了 `exit()` 系统调用的实现过程。

####2.1 _exit() 函数`_exit()` 函数是 `exit()` 系统调用的内部函数,它负责释放进程的虚拟地址空间和线程。`_exit()` 函数的实现如下:

c// mm/mmap.cvoid _exit(struct task_struct *tsk)
{
 struct mm_struct *mm = tsk->mm;

 exit_mm(mm);
 kthread_stop(tsk);
 kmem_cache_free(task_cachep, tsk);
}


在 `_exit()` 函数中,我们首先通过 `exit_mm()` 函数释放进程的虚拟地址空间。然后我们停止其线程,并释放其描述符。

####2.2 exit_group() 系统调用`exit_group()` 系统调用的实现如下:

c// sys_exit.cSYSCALL_DEFINE0(exit_group)
{
 struct task_struct *tsk = current;

 if (unlikely(!tsk))
 return -ESRCH;

 tsk->exit_code =0;
 exit_mm(tsk);
 kthread_stop(tsk);
 kmem_cache_free(task_cachep, tsk);

 return0;
}


在 `exit_group()` 系统调用中,我们首先通过 `current` 变量获取当前进程的描述符。然后我们设置进程的退出代码为0,释放其虚拟地址空间,并停止其线程。

### 总结本文讨论了 Linux 进程的创建和终止过程。在进程创建中,我们通过 `fork()` 系统调用创建一个新进程,新进程与父进程共享同样的虚拟地址空间。在进程终止中,我们通过 `exit()` 系统调用释放进程的虚拟地址空间和线程。

相关标签:linux
其他信息

其他资源

Top