Linux进程控制编程实验_02

任务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);
	}
    }
}
原创文章 8 获赞 2 访问量 1910

猜你喜欢

转载自blog.csdn.net/myszpl/article/details/105465555