相关概念:

程序:编译好的二进制文件,存放在磁盘上(占用的是物理内存空间),不占用系统资源(cpu,内存,打开的文件,设备,锁)

进程:抽象的概念,与操作系统原理联系紧密,是活跃的程序,占用系统资源,在内存中执行。

由原来的弹道程序涉及转换成多道程序设计,是CPU分成若干的时间碎片,各个进程抢占资源去执行,虽然程序有优先级高低,但是只是抢占到的几率高;即使是多核,也是需要时才开启其他核。

处理速度:

寄存器--cache--内存--硬盘--网络--存储介质

其他概念:串行和并发,CPU和MMU

进程控制块:PCB在usr/src/linux-headers/include/linux/sched.h文件中可以查看struct task_struct结构定义,包含部分定义,进程id,进程状态,进程切换时需要保存和恢复的CPU寄存器,描述虚拟的地址空间信息,当前工作目录,文件描述符表,用户id和组id,绘画和进程组,资源上限,umask掩码

进程状态

初始态(创建时,非常短暂),就绪态(有执行资格,但是没有执行权限,需要抢占资源),,运行态(正在执行),挂起态(没有执行资格和执行权限),终止态

linux进程守护(linux进程控制)(1)

进程控制

程序默认的是单进程的; 下面介绍多进程的使用

创建进程函数: pid_t fork(void);(查看 Linux下使用命令:man 2 fork)

linux进程守护(linux进程控制)(2)

返回值: 失败返回-1, 父进程返回子进程ID, 子进程返回0

查看当前进程 ps aux | grep "要查找的程序"; ps ajx

linux进程守护(linux进程控制)(3)

刚fork完成时(父子进程之间) 1. 0-3G地址空间相同 2. PCB相同, 但是pid除外 3.其他内容由mmu映射到物理内存上, 读时共享, 写时复制获取pid 和 ppid 对应的函数是getpid(); getppid();

//wait 函数回收子进程 #include <stdlib.h> #include <stdio.h> #include <unistd.h> int main() { pid_t pid; pid = fork(); if(pid == -1) { perror("fork error"); exit(-1); } else if(pid > 0) { printf("parent process\n"); } else if(pid == 0) { printf("child process\n"); } printf("mul process\n"); return 0; }

回收进程

进程有孤儿进程, 僵尸进程

  1. 孤儿进程 : 子进程活着, 父进程死了, linxu中的init进程会领养孤儿
  2. 僵尸进程 : 子进程死了, 父进程正在忙, 没有去回收子进程
  3. 进程回收 : 代码附在下边

wait - 阻塞函数

pid_t wait(int* status);

调用一次回收一个子进程资源

返回值:

0: 回收的子进程的pid;

-1: 没有子进程可以回收了;

status -- 传出参数

获取退出时候的返回值

waitpid -- pid_t waitpid(pid_t pid, int *status, int options);

(可以设置非阻塞, 提高wait的效率)

pid: -1: 所有的子进程

0: 当前进程组的子进程

0(pid): 回收指定进程的pcb

-pid: 回收不在当前进程组的子进程

opttions: 阻塞: 0

非阻塞: WNOHANG 可以设置为非阻塞

可以有针对性的回收某一个子进程资源 ;需要注意的是即使是非阻塞, 也需要循环来回收子进程

//wait函数回收子进程 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <sys/wait.h> int counter = 100; int main(int argc, const char* argv[]) { int number = 5; int i; pid_t pid; for(i=0; i<number; i) { pid = fork(); if(pid == 0) break; } if(i<number) { // 子进程 counter = 100; printf("child pid = %d, ppid = %d\n", getpid(), getppid()); printf("counter = %d\n\n", counter); //sleep(100); exit(9); } else if(i == number) { counter = 300; printf("parent pid = %d, ppid = %d\n", getpid(), getppid()); printf("counter = %d\n\n", counter); sleep(1); // 回收子进程 int status; pid_t wpid; while( (wpid=wait(&status)) != -1) { // 正常退出 if(WIFEXITED(status)) { printf("porcess exit by number: %d\n", WEXITSTATUS(status)); } // 被信号杀死 else if(WIFSIGNALED(status)) { printf("process kill by signal: %d\n", WTERMSIG(status)); } printf("child died pid = %d\n", wpid); } } return 10; }

//验证父子进程是否文件共享 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <fcntl.h> int main(int argc, const char* argv[]) { int fd = open("temp", O_CREAT | O_RDWR, 0664); if(fd == -1) { perror("open error"); exit(1); } pid_t pid = fork(); if(pid == -1) { perror("fork error"); exit(1); } if(pid > 0) { char* p = "123123123"; write(fd, p, strlen(p) 1); } else if(pid == 0) { // 睡1s保证父进程已经完成了文件的写操作 sleep(1); char buf[1024]; lseek(fd, 0, SEEK_SET); int len = read(fd, buf, sizeof(buf)); printf("%s\n", buf); } close(fd); return 0; }

//子进程执行不同任务, 父进程负责回收子进程 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> int main(int argc, const char* argv[]) { int i = 0; int number = 3; pid_t pid; for(i = 0; i<number; i) { pid = fork(); if(pid == 0) { break; } } // 父进程 if(i == number) { sleep(2); // 回收子进程 pid_t wpid; int status; while( (wpid = waitpid(0, &status, WNOHANG)) != -1 ) { if(wpid == 0) { continue; } printf("child pid = %d\n", wpid); if(WIFEXITED(status)) { printf("return number: %d\n", WEXITSTATUS(status)); } else if(WIFSIGNALED(status)) { printf("exit by signal: %d\n", WTERMSIG(status)); } } } else if(i == 0) { execl("/home/kevin/test/app", "app", NULL); } else if(i == 1) { execl("./error", "error", NULL); } else if(i == 2) { execlp("ps", "ps", "aux", NULL); } printf("over......\n"); return 0; }

//waitpid 来回收子进程, 注意非阻塞时也需要循环去回收 #include <stdio.h> #include <sys/wait.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> int main(int argc, const char* argv[]) { int num = 3; int i = 0; pid_t pid; for(i=0; i<num; i) { pid = fork(); if(pid == 0) { break; } } if(i == 0) { execlp("ps", "ps", "aux", NULL); perror("execlp ps"); exit(1); } else if(i == 1) { execl("/home/kevin/test/app", "app", NULL); perror("execl app"); exit(1); } else if(i == 2) { execl("./error", "error", NULL); perror("execl error"); exit(1); } else if(i == num) { // 回收 int status; pid_t wpid; while( (wpid = waitpid(-1, &status, WNOHANG)) != -1 ) { if(wpid == 0) continue; printf(" ----- child died pid = %d\n", wpid); if(WIFEXITED(status)) { printf("return value %d\n", WEXITSTATUS(status)); } else if(WIFSIGNALED(status)) { printf("died by signal: %d\n", WTERMSIG(status)); } } } return 0; }

,