执行mysh
后立马打印用户名welcome to mysh by <student ID>
,并显示当前工作目录 <username> in <current working directory>
思路:编写函数mysh_print_promt()
输出信息,放在mysh
主循环的最开头调用,就能在每次巡回时打印信息。
实现如下:
#define PATH_BUFSIZE 1024
void mysh_print_promt() {
/* Print "<username> in <current working directory>" */
char namebuf[PATH_BUFSIZE];
getlogin_r(namebuf, sizeof(namebuf));
printf("%s in ", namebuf);
char pathbuf[PATH_BUFSIZE];
getcwd(pathbuf, sizeof(pathbuf));
printf("%s\n", pathbuf);
/* Print ">mysh " */
printf(">mysh");
}
将读进的每一行解析到 command 结构的各个变量中,由 mode 控制前后台执行
- 需要搜索字符串中的特定字符 &
- 字符串处理,分割字符字符串到 command 结构中
- 链表初始化后怎么释放申请的内存?
对简单情形 mysh >> who | sort | cat
而言在
fur (cur_segment = command->root; cur_segment != NULL; cur_segment->next)
中cur
依次遍历 Link list时
-
cur 分别指向 who 和 sort 时如何区分二者的 in_fd
-
不在child 和 parent 中加入
close
语句,parent 会出现 block
实现Ctrl C
中断mysh
创建的子进程,但不结束自身
实现Ctrl Z
将 mysh
创建的子进程挂起,但不将自身挂起
使用系统调用 signal
Ctrl C
产生SIGINT
,默认动作是使进程结束Ctrl Z
产生SIGTSTP
,默认动作是使进程停止SIG_DFL
表示对信号的响应取默认SIG_IGN
表示忽略捕获到的信号
parent process 和 child process 都会捕获到键盘输入的信号,但是各自对信号的响应不同。
所以要在child 中加入如下语句:
signal(SIGINT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
parent 中加入如下语句:
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
Ctrl Z
后会出现 parent process block 现象,原因是child process 捕获挂起信号后挂起,而parent 在wait 语句中等待child process 执行结束。
需要使用watipid
的 WUNTRACED
option, 表示当child stop 时waitpid
即可以返回,而不是block。
参考 man watipid
- fg 实现将挂起的进程调到前台继续执行
- bg 实现将挂起的进程在后台继续执行
两者都要向进程号发送SIGCONT
信号
使用如下语句:
kill(pid, SIGCONT);
在子进程中捕获该信号,并设置默认响应
signal(SIGCONT, SIG_DFL);
將挂起的子进程,fb 拉回前景或bg 继续使其在背景执行,那么子进程执行完后会变成zombie
需要在fb 和 bg 函数中加入wait 语句等待子进程的结束。
可以同过设置printf 打印出彩色的提示,从而修饰shell 解释的显示风格。