任务1:编写一个进程创建实验程序task51.c,创建如图所示的进程族亲结构,其中p1是程序启动时由加载程序创建第一个进程。各进程的输出信息分别如下:
p1:I am father process
p11: 当前时间是< 年 月 日 时 分 秒>
p12: I am young brother process
p121:我的学号是<您的学号xxx>
p122:我的姓名是<您的姓名xxx>
提示:获得当前系统时间的函数是 time_t time(time_t *t);
将time_t类型的的时间转换成时间字符串的函数是:char *ctime(const time_t *timep);
#include<stdio.h>
#include<time.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
printf("I am father process\n");//p1打印
if(fork() == 0)//p11输出时间
{
time_t timep;
time(&timep);
printf("%s",ctime(&timep));
}
else
{
if(fork() == 0)
{
printf("I am young brother process\n");//p12打印
if(fork() == 0)//p121输出学号
{
printf("2018\n");
}
else
{
if(fork() == 0)//p122输出名字
printf("name\n");
}
wait(NULL);//p12等待子线程完成
}
wait(NULL);//p1等待子线程完成
}
}
任务2:参考教材shellex.c代码,实现一个简单的交互式shell程序task52.c,具备的功能至少有:
(1)打印提示符%;获取用户输入指令;解析指令;寻找命令文件,执行指令
(1)显示命令提示符%;
(2)获取用户输入指令;解析指令;寻找命令文件,执行指令;
(3)前一个命令完成后才继续显示命令提示符%,等待用户输入下一条命令;
(3)如果输入“exit”或“logout”,则退出shell.
(4)允许命令参数间有多个空格,也允许命令前后有空格
(5)支持输出重定向和管道功能。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<fcntl.h>
#define Max 50
void eval_f(char* command);//执行需要重定向的命令行
void eval(char * command);//执行不需要重定向的命令行
void pa();//接受父进程接受子进程信号SIGUSR1处理函数
int main(){
char com[Max];//接收命令
while(1){
printf("%%");
fgets(com,Max,stdin);
int num = strlen(com);
com[num-1]='\0';//fgets函数会把最后一位\n传入字符串
if(fork()==0)//子进程解析并执行命令行
{
if(strstr(com,"<")!=NULL)//是否包含重定向标准
eval_f(com);
else
eval(com);
exit(0);//子进程退出 以免影响后续进行
}
else{
signal(SIGUSR1,pa);//接收子进程信号
wait(NULL);//等待子进程结束
}
}
}
void eval(char* com){
char * arv[Max];
//利用strtok函数分割字符串
if((arv[0] = strtok(com," "))==NULL)//只有单个命令 例如:ls
arv[0] = com;
else{//命令+参数 例如 ls -l
int cnt =1;//the count of arv
while((arv[cnt] = strtok(NULL," ")) != NULL){
cnt++;
}
}
//特殊标识处理
if(arv[0]==NULL||!strcmp(arv[0],"exit")||!strcmp(arv[0],"logout")){
kill(getppid(),10);
return;
}
if(execvp(arv[0],arv)<0){//evecvp执行命令,成功不返回,失败返回-1
printf("%s Command not found\n",arv[0]);
}
return;
}
void eval_f(char* command){
char* com,*file;
file = strstr(command,"<")+1;
file = strtok(file," ");//提取文件名
com = strtok(command,"<");//提取命令
int fd,save_fd;
fd = open(file,O_WRONLY|O_CREAT|O_TRUNC,0777);
//先把输出保存后再关掉,dup2函数使输出接到文件,输出后关闭并还原终端输出
//具体见下图
save_fd = dup(STDOUT_FILENO);
dup2(fd,STDOUT_FILENO);
close(fd);
eval(com);
dup2(save_fd,STDOUT_FILENO);
close(save_fd);
}
void pa(){
exit(0);
}
任务3:写一个信号机制实验程序task53.c,由父进程创建两个子进程,通过终端输入Crtl+\组合键向父进程发送SIGQUIT软中断信号或由系统时钟产生SIGALRM软中断信号发送给父进程;父进程接收到这两个软中断的其中某一个后,向其两个子进程分别发送整数值为SIGUSR1 (10)和SIGUSR2(12)软中断信号,子进程获得对应软中断信号后,分别输出“<进程PID> killed by <信号编号>”后,终止运行;父进程调用wait()函数等待两个子进程终止,然后自我终止。
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
pid_t pid1,pid2;
void pa(int sig)
{
kill(pid1, 10);
kill(pid2, 12);
}
void child(int sig)
{
printf("%d killed by %d\n",getpid(),sig);
}
int main()
{
signal(SIGQUIT,SIG_IGN);//防止子进程提前退出
if(pid1 = fork() == 0)
{
signal(SIGUSR1,child);
pause();
exit(0);
}
else{
if(pid2 = fork() ==0)
{
signal(SIGUSR2,child);
pause();
exit(0);
}
else
{
//10秒后没有接收到ctrl+\发送的SIGQUIT信号则向主进程发送时钟信号
alarm(10);
signal(SIGALRM,pa);
signal(SIGQUIT,pa);
pause();
wait(NULL);
}
}
}