本文主要探究linux下的进程相关知识点,包括进程的创建、状态、等待和结束
1. 进程创建
调用fork,可以创建新的进程,fork调用的特点如下:
(1)调用一次返回两次,在子进程中返回一次,在父进程中返回一次
(2)返回值分两种,子进程返回0, 父进程返回子进程的进程ID
创建的子进程的特点:
(1)子进程获得父进程数据空间、堆、栈等资源的副本。
在父进程中打开的文件,管道,socket等,都会在子进程中保留一个副本,所以不用的话,需要将其关闭
(2)子进程有自己独立的地址空间。
示例如下,创建子进程,子进程可以访问fork之前父进程的一些对象,但是对其改变不会影响父进程。
#include <unistd.h>
#include <iostream>
#include <sys/types.h>
using namespace std;
int main(int argc, char **argv)
{
int test_1 = 111;
int *test_2 = new int;
*test_2 = 222;
pid_t pid = fork();
if (pid < 0)
{
cout << "fork error" << strerror(errno) << endl;
}
else if (pid == 0)
{
cout << "child process" << endl;
test_1 = 122;
*test_2 = 233;
cout << "after child process modify test1 and test_2" << endl;
cout << "child process, &test_1:" << &test_1 << ", test_1:" << test_1 << endl;
cout << "child process, &test_2:" << test_2 << ", test_2:"<< *test_2 << endl;
delete test_2;
cout << "after child process delete test_2" << endl;
}
else if (pid > 0)
{
cout << "parent process" << endl;
sleep(3);
cout << "parent process, &test_1:" << &test_1 << ", test_1:" << test_1 << endl;
cout << "parent process, &test_2:" << test_2 << ", test_2:"<< *test_2 << endl;
delete test_2;
}
return 0;
}
执行结果如下,可见在子进程中可以访问fork前创建的变量,并且修改其值并不会影响父进程。
不过 &test_1 和 test_2,在父进程和子进程中其值都一样,也许这个是一个相对地址,有待进一步细究。
2. 进程状态
linux 下的进程状态有以下几种
(1)R (TASK_RUNNING),可执行状态
进程处于可执行队列中,等待系统调度进行处理
(2)S (TASK_INTERRUPTIBLE),可中断的休眠状态
进程等待某个事件的发生(等待socket链接,等待信号量等等),而被挂起,即通常所说的被阻塞,放入对应事件的等待队列中。
这些事件发生时(外部中断触发或其他进程触发),对应等待队列中的一个或多个进程将被唤醒。
进程可以响应外部信号,如执行 kill -9 100,进程号为100的进程将被杀死退出。
(3)D (TASK_UNINTERRUPTIBLE),不可中断的休眠状态
类似 TASK_INTERRUPTIBLE 状态,不过进程并不响应外部的信号,用于某些不可被中断的特殊操作中。
(4)T (TASK_STOPPED || TASK_TRACED),暂停状态或跟踪状态
关于 TASK_STOPPED
进程处于暂停状态,即即使所有条件都满足,也不能加入执行对列等待系统调度处理。
向进程发送SIGSTOP,进程就会进入TASK_STOPPED 状态,再向其发送SIGCONT信号,进程可恢复到 TASK_RUNNING 状态
关于 TASK_TRACED
类似 TASK_STOPPED,进程处于暂停状态,等待跟踪它的进程对他进行操作。
比如在 gdb 中对进程下一个断点,进程在端点处停下来的时候就处于 TASK_TRACED 状态
调试进程退出或通过系统调用 ptrace 执行 PTRACE_COND,PTRACE_DETACH 后,进程将恢复 TASK_RUNNING 状态
处于 TASK_TRACED 的进程,不响应 SIGCONT 信号而变成 TASK_RUNNING 状态。
(5)Z (TASK_DEAD && TASK_ZOMBIE),退出状态,进程成为僵尸进程
在退出过程中,进程占有的所以资源被收回,除了 task_struct 结构。进程仅剩余 task_struct 这个空壳,称为僵尸进程。
(6)X (TASK_DEAD && EXIT_DEAD),退出状态,进程即将被销毁
后面对这些状态进行详细的了解,此处不做更多分析。
(2)进程等待与结束