gem-universe / blog

0 stars 0 forks source link

[操作系统]15. 操作系统上的进程 #18

Open supergem3000 opened 8 months ago

supergem3000 commented 8 months ago

15. 操作系统上的进程 (jyywiki.cn)

线程、进程和操作系统

操作系统同时保存多个状态机。 进程有自己的内存空间,看不到其他进程的内存空间。线程共享内存。

在 UNIX/Linux 系统内核完成初始化后,只有一个 init 进程被启动,从此以后,操作系统内核就化身为了一个事件驱动的程序、状态机的管理者,仅在中断和系统调用发生时开始执行。 那么SysCall必须有两个系统调用:创建进程(创建状态机),终止进程(终止状态机)

复制状态机:fork()

创建状态机应该提供什么样的 API?UNIX 的答案:fork

int fork();

做一份状态机完整的复制(内存、寄存器)。除了fork返回值不同。 fork:复制失败返回-1,新创建进程返回0,执行fork的进程返回子进程的进程号。 因为状态机是复制的,因此总能找到父子关系。 因此有了进程树(pstree)

理解fork:习题1

pid_t x = fork();
pid_t y = fork();
printf("%d %d\n", x, y);

到底创建了几个状态机?输出是什么? 答:创建了4个,输出可能性很多,比如{id1} {id2}\n {id1} 0\n 0 {id3}\n 0 0\n

理解fork:习题2

for (int i = 0; i < 2; i++) {
  fork();
  printf("Hello\n");
}

重置状态机:execve()

状态机只是复制,怎么创建出各种各样的进程呢?怎么把复制出的程序变成另外一个程序呢? UNIX 的答案:execve。将当前进程重置成一个可执行文件描述状态机的初始状态

int execve(const char *filename,
           char * const argv[], char * const envp[]);

execve行为:执行名为filename的程序,允许对新状态机设置参数argv和环境变量envp,对应main的参数。 execve是唯一能够“执行程序”的系统调用。因此也是strace的第一个系统调用。

销毁状态机:_exit()

还缺少一个销毁状态机的函数。 UNIX的答案:_exit

exit是c语言标准库,为了区分开加了下划线

void _exit(int status);

销毁当前状态机,并允许有一个返回值。 子进程终止会通知父进程。 几种exit的不同:

  • exit(0) stdlib.h中声明,c语言main运行完实际还会有一段代码(等于把写的程序做了一层包装)。调用exit,自己写的程序停止,包装代码还会运行到结束。
  • _exit(0) glibc中的syscall wrapper。终止整个进程,执行exit_group系统调用。进程直接停止,上面说的包装代码不会运行。
  • syscall(SYS_exit, 0) 执行exit系统调用终止当前线程。线程直接停止,上面说的包装代码不会运行。