进程退出
1.进程退出的场景
①代码运行完毕正常退出,结果正确
②代码运行完毕正常退出,结果不正确
③异常退出
常见退出方法
正常退出
- 从main() 函数中返回return退出
- 调用exit()函数退出
exit:
#include <unistd.h>
void exit(int status);
参数:status 定义了进程的终止状态,父进程通过wait来获取该值
- 调用_exit()函数退出
_exit:
#include <unistd.h>
void _exit(int status);
exit最后也会调用exit, 但在调用exit之前,还做了其他工作
异常退出
ctrl + c,信号终止。
进程等待
子进程退出,父进程不管,就会造成僵尸进程的问题,导致内存泄漏,还需要知道父进程给子进程的任务完成的怎么样,所以需要回收子进程资源,获取子进程的退出信息。采用wait和waitpid的方法。
status:
提取低七位:status & 0x7F。
提取退出码:(status>> 8) & 0xFF
进程替换
进程在被调度时,找到进程的PCB,就可以通过对应的进程地址空间加页表,找到这个进程对应的代码和数据,进程替换,PCB不变,进程地址空间不变,页表不变,把目标文件的代码数据加载进来,之前的代码数据就被替换了,进程PCB再通过进程地址空间加页表映射的就是新的代码数据。
迷你shell
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #define MAX_CMD 1024
7 char command[MAX_CMD];
8 int do_face()
9 {
10 memset(command, 0x00, MAX_CMD);
11 printf("minishell$ ");
12 fflush(stdout);
13 if (scanf("%[^\n]%*c", command) == 0)
14 {
15 getchar();
16 return -1;
17 }
18 return 0;
19 }
20 char **do_parse(char *buff)
21 {
22 int argc = 0;
23 static char *argv[32];
24 char *ptr = buff;
25 while(*ptr != '\0')
26 {
21 {
22 int argc = 0;
23 static char *argv[32];
24 char *ptr = buff;
25 while(*ptr != '\0')
26 {
27 if (!isspace(*ptr))
28 {
29 argv[argc++] = ptr;
30 while((!isspace(*ptr)) && (*ptr) != '\0')
31 {
32 ptr++;
33 }
34 }
35 else
36 {
37 while(isspace(*ptr))
38 {
39 *ptr = '\0';
40 ptr++;
41 }
42 argv[argc] = NULL;
43 return argv;
44 }
45 }
46 }
47 int do_exec(char *buff)
48 {
49 char **argv = {NULL};
50 int pid = fork();
51 if (pid == 0)
52 {
53 argv = do_parse(buff);
54 if (argv[0] == NULL)
55 {
56 exit(-1);
57 }
58 execvp(argv[0], argv);
59 }
60 else
61 {
62 waitpid(pid, NULL, 0);
63 }
64 return 0;
65 }
66 int main(int argc, char *argv[])
67 {
68 while(1)
69 {
70 if (do_face() < 0)
71 continue;
72 do_exec(command);
73 }
74 return 0;
75 }