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()` 系统调用释放进程的虚拟地址空间和线程。