可以看到 Pause 容器做如下两件事情:
- 注册各种信号处理函数,主要处理两类信息:退出信号和 child 信号。收到 SIGINT 或是 SIGTERM 后,直接退出。收到 SIGCHLD 信号,调用 waitpid, 回收退出进程
- 主进程 for 循环调用 pause() 函数,使进程进入休眠状态,直到被终止或是收到信号
可疑的 waitpid
还是 c 的基础不够扎实,一直以为 waitpid 是父进程等待回收退出的子进程,但是真的这样嘛?
- zerun.dong$ man waitpid
- WAIT(2) BSD System Calls Manual WAIT(2)
- NAME
- wait, wait3, wait4, waitpid — wait for process termination
- SYNOPSIS
- #include <sys/wait.h>
在 mac 上查看 man 手册,wait for process termination 也确实这么写的。登到 ubuntu 18.04 查看一下
- :~# man waitpid
- WAIT(2) Linux Programmer's Manual WAIT(2)
- NAME
- wait, waitpid, waitid – wait for process to change state
对于 linux man 手册,就变成了 wait for process to change state 等待进程的状态变更!!!
- All of these system calls are used to wait for state changes in a child of the calling process, and obtain information about the child whose
- state has changed. A state change is considered to be: the child terminated; the child was stopped by a signal; or the child was resumed by
- a signal. In the case of a terminated child, performing a wait allows the system to release the resources associated with the child; if a
- wait is not performed, then the terminated child remains in a "zombie" state (see NOTES below).
并且还很贴心的提供了测试代码
- #include <sys/wait.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <stdio.h>
- int main(int argc, char *argv[])
- {
- pid_t cpid, w;
- int wstatus;
- cpid = fork();
- if (cpid == -1) {
- perror("fork");
- exit(EXIT_FAILURE);
- }
- if (cpid == 0) { /* Code executed by child */
- printf("Child PID is %ld ", (long) getpid());
- if (argc == 1)
- pause(); /* Wait for signals */
- _exit(atoi(argv[1]));
- } else { /* Code executed by parent */
- do {
- w = waitpid(cpid, &wstatus, WUNTRACED | WCONTINUED);
- if (w == -1) {
- perror("waitpid");
- exit(EXIT_FAILURE);
- }
- if (WIFEXITED(wstatus)) {
- printf("exited, status=%d ", WEXITSTATUS(wstatus));
- } else if (WIFSIGNALED(wstatus)) {
- printf("killed by signal %d ", WTERMSIG(wstatus));
- } else if (WIFSTOPPED(wstatus)) {
- printf("stopped by signal %d ", WSTOPSIG(wstatus));
- } else if (WIFCONTINUED(wstatus)) {
- printf("continued ");
- }
- } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
- exit(EXIT_SUCCESS);
- }
- }
子进程一直处于 pause 状态,而父进程则调用 waitpid 等待子进程状态变更。让我们开启一个 session 运行代码,另外一个 session 发送信号
- ~$ ./a.out
- Child PID is 70718
- stopped by signal 19
- continued
- stopped by signal 19
- continued
- ^C
- ~# ps aux | grep a.out
- zerun.d+ 70717 0.0 0.0 4512 744 pts/0 S+ 06:48 0:00 ./a.out
- zerun.d+ 70718 0.0 0.0 4512 72 pts/0 S+ 06:48 0:00 ./a.out
- root 71155 0.0 0.0 16152 1060 pts/1 S+ 06:49 0:00 grep –color=auto a.out
- ~#
- ~# kill -STOP 70718
- ~#
- ~# ps aux | grep a.out
- zerun.d+ 70717 0.0 0.0 4512 744 pts/0 S+ 06:48 0:00 ./a.out
- zerun.d+ 70718 0.0 0.0 4512 72 pts/0 T+ 06:48 0:00 ./a.out
- root 71173 0.0 0.0 16152 1060 pts/1 S+ 06:49 0:00 grep –color=auto a.out
- ~#
- ~# kill -CONT 70718
- ~#
- ~# ps aux | grep a.out
- zerun.d+ 70717 0.0 0.0 4512 744 pts/0 S+ 06:48 0:00 ./a.out
- zerun.d+ 70718 0.0 0.0 4512 72 pts/0 S+ 06:48 0:00 ./a.out
- root 71296 0.0 0.0 16152 1056 pts/1 R+ 06:49 0:00 grep –color=auto a.out
通过向子进程发送信号 STOP CONT 来控制进程。
看来不同操作系统,同名 c 函数行为是不太一样的。大惊小怪,就是菜:(
共享哪些 NS
一般提起 POD 就知道,同一个 POD 内的容器如果互相访问,只需调用 localhost 即可。如果把 k8s 集群想象成分布式操作系统,那么 POD 就是进程组的概念,一定要共享某些东西的,那么默认共享哪些 namespace 呢?
使用 minikube 搭建环境,先看一下 POD 定义文件