hello~ 很高兴见到大家! 这次带来的是Linux系统中关于进程控制这部分的一些知识点,如果对你有所帮助的话,可否留下你宝贵的三连呢? 个 人 主 页: 默|笙

156 int main()
157 {
158 Loadenv();
159 char command_line[MAXSIZE] = {0};
160 while(1)
161 {
162 //打印命令行字符串
163 PrintCommandLine();
164 //获取用户输入的字符串
165 if (0 ==GetCommand(command_line, sizeof(command_line)))
166 {
167 continue;
168 }
169
170 //解析字符串
171 ParseCommand(command_line);
172 //检查一个命令是要由bash执行的内建命令,还是要让子进程执行的普通命令
173 if(CheckBuiltinExecute() > 0)
174 continue;
175 //执行解析出来的字符串
176 ExecuteCommand();
177 }
178 return 0;
179 } 16 //环境变量表
17 int genvc = 0;
18 char* genv[MAXARGS];
23 void Loadenv()
24 {
25 //正常情况下这个Shell它是从配置文件里面读取环境变量
26 //但这里我们没办法实现,因为非常复杂
27 //所以就直接从bash里面读取了
28 extern char** environ;
29 for(; environ[genvc]; genvc++)
30 {
31 genv[genvc] = (char*)malloc(sizeof(char) * 4096);
32 strcpy(genv[genvc], environ[genvc]);
33 }
34 genv[genvc] = NULL;
35
36 for (int i = 0; genv[i]; i++)
37 {
38 printf("genv[%d]: %s\n", i, genv[i]);
39 }
40 }
//后面添加的函数,用于提取路径最后的那个文件名
43 std::string rfindDir(const std::string &p)
44 {
45 if(p == "/")
46 return p;
47 const std::string psep = "/";
48 auto pos = p.rfind(psep);
49 if(pos == std::string::npos)
50 return std::string();
51 return p.substr(pos+1); // /home/whb
52 }
9 //获取用户名
10 const char* GetUsername()
11 {
12 char* name = getenv("USER");
13 if (name == NULL)
14 return "None";
15 return name;
16 }
17 //获取主机名
18 const char* GetHostname()
19 {
20 char* hostname = getenv("HOSTNAME");
21 if (hostname == NULL)
22 return "None";
23 return hostname;
24 }
25 //获取pwd当前路径
26 const char* GetPwd()
27 {
28 char* pwd = getenv("PWD");
29 if (pwd == NULL)
30 return "None";
31 return pwd;
32 }
33 //打印命令行字符串函数
34 void PrintCommandLine()
35 {
36 printf("[%s@%s %s]#", GetUsername(), GetHostname(), rfindDir(GetPwd()).c_str());
37 fflush(stdout);
38 } 41 #define MAXSIZE 128
49 int GetCommand(char* commandline, int size)
50 {
51 if(NULL == fgets(commandline, size, stdin))
52 return 0;
53 //用户输入的时候至少会摁一下回车键,把回车键所在位置置为'\0'
54 commandline[strlen(commandline) - 1] = '\0';
55 //printf("%s\n", commandline);
56 return strlen(commandline);
57 }
//while循环外
92 char command_line[MAXSIZE] = {0};
//main函数while循环里
97 //获取用户输入的字符串
98 if (0 ==GetCommand(command_line, sizeof(command_line)))
99 {
100 continue;
101 }

//全局
42 #define MAXARGS 32
43
44 //命令行参数表
45 int gargc = 0;
46 char* gargv[MAXARGS];
47 const char* gsep = " ";
59 void ParseCommand(char* commandline)
60 {
61 gargc = 0;
62 memset(gargv, 0, sizeof(gargv));
63
64 gargv[0] = strtok(commandline, gsep);
//strtok先切割返回一个值,再把这个值存入gargv[++gargc]里面,再检测这个值
65 while ((gargv[++gargc] = strtok(NULL, gsep)));
69 }151 //检查一个命令是要由bash执行的内建命令,还是要让子进程执行的普通命令
152 if(CheckBuiltinExecute() > 0)
153 continue;

49 //我们的Shell自己所处的工作路径
50 char cwd[MAXSIZE];
75 if (strcmp(gargv[0], "cd") == 0)
76 {
77 if (gargc == 2)
78 {
79 chdir(gargv[1]);
80
81 //修改环境变量
82 char pwd[1024];
83 //存储当前获取到的工作路径到pwd里面
84 getcwd(pwd, sizeof(pwd));
85 //拼接PWD环境变量
86 snprintf(cwd, sizeof(cwd), "PWD=%s", pwd);
87 //导入环境变量cwd
88 putenv(cwd);
89 return 1;
90 } 51 //上一次命令执行完毕后的退出码
52 int lastcode = 0;
94 else if (strcmp(gargv[0], "echo") == 0)
95 {
96 if (gargc == 2)
97 {
98 if (gargv[1][0] == '$')
99 {
100 if (strcmp(gargv[1]+1, "?") == 0)
101 {
102 printf("%d\n", lastcode);
103 }
104 else if (strcmp(gargv[1]+1, "PATH") == 0)
105 {
106 printf("%s\n", getenv("PATH"));
107 }
108 lastcode = 0;
109 return 1;
110 }
111 }
112 } 71 int ExecuteCommand()
72 {
73 pid_t id = fork();
74 if (id == 0)
75 {
76 execvp(gargv[0], gargv);
77 exit(0);
78 }
79 else if (id < 0)
80 return -1;
81 else
82 {
83 int status = 0;
84 pid_t sid = waitpid(id, &status, 0);
85 if (sid > 0)
lastcode = WEXITSTATUS(status);
86 //printf("wait childprocess sucess!!!\n");
87 }
88 return 0;
89 } 1 #include<stdio.h>
2 #include<unistd.h>
3 #include<string.h>
4 #include<stdlib.h>
5 #include<sys/types.h>
6 #include<sys/wait.h>
7 #include<iostream>
8 #include<string>
9
10 #define MAXSIZE 128
11 #define MAXARGS 32
12
13 //命令行参数表
14 int gargc = 0;
15 char* gargv[MAXARGS];
16 const char* gsep = " ";
17 //环境变量表
18 int genvc = 0;
19 char* genv[MAXARGS];
20 //我们的Shell自己所处的工作路径
21 char cwd[MAXSIZE];
22 //上一次命令执行完毕后的退出码
23 int lastcode = 0;
24
25 void Loadenv()
26 {
27 //正常情况下这个Shell它是从配置文件里面读取环境变量
28 //但这里我们没办法实现,因为非常复杂
29 //所以就直接从bash里面读取了
30 extern char** environ;
31 for(; environ[genvc]; genvc++)
32 {
33 genv[genvc] = (char*)malloc(sizeof(char) * 4096);
34 strcpy(genv[genvc], environ[genvc]);
35 }
36 genv[genvc] = NULL;
37
38 for (int i = 0; genv[i]; i++)
39 {
40 printf("genv[%d]: %s\n", i, genv[i]);
41 }
42 }
43 std::string rfindDir(const std::string &p)
44 {
45 if(p == "/")
46 return p;
47 const std::string psep = "/";
48 auto pos = p.rfind(psep);
49 if(pos == std::string::npos)
50 return std::string();
51 return p.substr(pos+1); // /home/whb
52 }
53 //获取用户名
54 const char* GetUsername()
55 {
56 char* name = getenv("USER");
57 if (name == NULL)
58 return "None";
59 return name;
60 }
61 //获取主机名
62 const char* GetHostname()
63 {
64 char* hostname = getenv("HOSTNAME");
65 if (hostname == NULL)
66 return "None";
67 return hostname;
68 }
69 //获取pwd当前路径
70 const char* GetPwd()
71 {
72 char* pwd = getenv("PWD");
73 if (pwd == NULL)
74 return "None";
75 return pwd;
76 }
77 //打印命令行字符串函数
78 void PrintCommandLine()
79 {
80 printf("[%s@%s %s]#", GetUsername(), GetHostname(), rfindDir(GetPwd()).c_str());
81 fflush(stdout);
82 }
83
84
85 int GetCommand(char* commandline, int size)
86 {
87 if(NULL == fgets(commandline, size, stdin))
88 return 0;
89 //用户输入的时候至少会摁一下回车键,把回车键所在位置置为'\0'
90 commandline[strlen(commandline) - 1] = '\0';
91 //printf("%s\n", commandline);
92 return strlen(commandline);
93 }
94
95 void ParseCommand(char* commandline)
96 {
97 gargc = 0;
98 memset(gargv, 0, sizeof(gargv));
99
100 gargv[0] = strtok(commandline, gsep);
101 while ((gargv[++gargc] = strtok(NULL, gsep)));
102 //int i = 0;
103 //for (i = 0; i < gargc; i++)
104 // printf("%s\n", gargv[i]);
105 }
106
107 int CheckBuiltinExecute()
108 {
109 if (strcmp(gargv[0], "cd") == 0)
110 {
111 if (gargc == 2)
112 {
113 chdir(gargv[1]);
114
115 //修改环境变量
116 char pwd[1024];
117 //存储当前获取到的工作路径到pwd里面
118 getcwd(pwd, sizeof(pwd));
119 //拼接PWD环境变量
120 snprintf(cwd, sizeof(cwd), "PWD=%s", pwd);
121 //导入环境变量cwd
122 putenv(cwd);
123 }
124 return 1;
125 }
126 else if (strcmp(gargv[0], "echo") == 0)
127 {
128 if (gargc == 2)
129 {
130 if (gargv[1][0] == '$')
131 {
132 if (strcmp(gargv[1]+1, "?") == 0)
133 {
134 printf("%d\n", lastcode);
135 }
136 else if (strcmp(gargv[1]+1, "PATH") == 0)
137 {
138 printf("%s\n", getenv("PATH"));
139 }
140 lastcode = 0;
141 return 1;
142 }
143 }
144 }
145
146 return 0;
147 }
148 int ExecuteCommand()
149 {
150 pid_t id = fork();
151 if (id == 0)
152 {
153 execvp(gargv[0], gargv);
154 exit(0);
155 }
156 else if (id < 0)
157 return -1;
158 else
159 {
160 int status = 0;
161 pid_t sid = waitpid(id, &status, 0);
162 if (sid > 0)
163 lastcode = WEXITSTATUS(status);
164 //printf("wait childprocess sucess!!!\n");
165 }
166 return 0;
167 }
168 int main()
169 {
170 Loadenv();
171 char command_line[MAXSIZE] = {0};
172 while(1)
173 {
174 //打印命令行字符串
175 PrintCommandLine();
176 //获取用户输入的字符串
177 if (0 ==GetCommand(command_line, sizeof(command_line)))
178 {
179 continue;
180 }
181
182 //解析字符串
183 ParseCommand(command_line);
184 //检查一个命令是要由bash执行的内建命令,还是要让子进程执行的普通命令
185 if(CheckBuiltinExecute() > 0)
186 continue;
187 //执行解析出来的字符串
188 ExecuteCommand();
189 }
190 return 0;
191 } 今天的分享就到此结束啦,如果对读者朋友们有所帮助的话,可否留下宝贵的三连呢~~ 让我们共同努力, 一起走下去!