linux 操作 系统编程【笔记 续】

8 篇文章 0 订阅
6 篇文章 0 订阅

学习目标:

进程替换


学习内容:

所谓的进程替换,不会创建新的进程,只是将进程执行的指令和数据替换成新的程序。

内容:fork和vfork,死锁

int exec(const char *path,char *argv0,char *argv1, ... ,char *argvn,(cahr*)0 );//l--list ,从argv0到argvn对应的就是新程序main方法的参数
//本身main的argv[0]是执行的命令,是要传的;但在这里,可以不传argv[0]
int execv(const char *path,char *argv[]);//v--向量

int execle(const char *path,char *argv0,char *argv1, ... ,char *argvn,(cahr*)0 ,char *envp[]);//环境变量

int execve(const char *path,char *argv[],char *envp[]);//是唯一的系统调用

int execlp(const cahr* file,char *argv0,char *argv1, ... ,char *argvn,(cahr*)0);//file如果指定路径,有就去找,如果没有,就通过环境变量PATH查找

int execvp(const char *file,char *argv[]);

strace ./ppp

如果exec这些方法调用成功,则会用新程序替换当前进程的程序,在exec调用之后的所有指令都不会被调用,无法接受返回值。如果exec调用失败,替换不成功,exec之后的指令才会执行。

程序mian.c + exec.c

仿写bash:命令解析器

功能:获取用户输入的命令,根据命令执行相应的操作

​ 大部分的命令都不是集成在bash中,而是单独实行的 e,g ls ps pwd su touch等

在这里插入图片描述

在这里插入图片描述

代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<signal.h>
#include<sys/utsname.h>
#include<pwd.h>

#define STRLEN 128

void Zombie(int sign)
{
	wait(NULL);
}

void ShowTagInfo()
{
	signal(SIGCHLD,Zombie);
	//用户名@主机名 路径 $/#
	struct utsname host_name;
	uname(&host_name);

	struct passwd *p=getpwuid(getuid());
	assert(p!=NULL);

	char now_pwd[STRLEN];
	getcwd(now_pwd,STRLEN-1);
	char ch[STRLEN]={0};
	if(strncmp(now_pwd,p->pw_dir,strlen(p->pw_dir))==0)
	{
		strcat(ch,"~");
		strcat(ch,now_pwd+strlen(p->pw_dir));
	}
	else
	{
		strcat(ch,now_pwd);
	}
	

	char tag='$';
	if(getuid()==0)
		tag='#';
	//printf("%s@%s:%s%c ",getlogin(),host_name.nodename,now_pwd,tag);
	printf("\033[1;36m""%s@%s:""\033[0m",getlogin(),host_name.nodename);
	printf("\033[1;34m""%s""\033[0m",ch);
	printf("%c ",tag);

	
}

void CutString(char *cmd,char *arr[])
{
	char *p;
	p=strtok(cmd," ");
	int index=0;
	while(p)
	{
		arr[index++]=p;
		p=strtok(NULL," ");
	}
}
void MyCdCommand(char *path)
{
	static char old_pwd[STRLEN]={0};//保存上次所在位置
	printf("输入的:%s\n",path);

    char dest_path[STRLEN]={0};

	if(path==NULL || strncmp(path,"~",1)==0 )//切换到家目录
	{
		struct passwd *pw=getpwuid(getuid());
		assert(pw!=NULL);

		strcpy(dest_path,pw->pw_dir);

		if(strlen(path) > 1) // ~/xxx/xx
		{
			strcat(dest_path,path+1);
		}
		
	}
	else if( strncmp(path,"-",1)==0)//切换到上一次的位置
	{
		if(strlen(old_pwd)==0)
		{
			printf("cd is error\n");
			return;
		}
		strcpy(dest_path,old_pwd);
	}
	else
	{
		strcpy(dest_path,path);
	}
	
	char now_pwd[STRLEN]={0};
	getcwd(now_pwd,STRLEN-1);
	printf("It's now_pwd:%s\n",now_pwd);

	if(chdir(dest_path)==-1)
	{
		perror("cd is error");
		return;
	}
	
	memset(old_pwd,0,STRLEN);//清空一下,再拷贝
	strcpy(old_pwd,now_pwd);
	
}

void DealExec(char *arr[],int is_back)
{
	pid_t pid=vfork();
	assert(pid!=-1);

	if(pid==0)//前台处理
	{
		char file[STRLEN]="/home/zff/Desktop/系统编程/0417/shell/mybin/";
		if(strstr(arr[0],"/")!=NULL)
		{
			strcpy(file,arr[0]);
		}
		else
		{
			strcat(file,arr[0]);
		}

		execv(file,arr);//如果命令不在,exec就会失败
		//fflush(shutout);
		perror("execv");
		exit(0);
	}
	else//后台处理
	{
		if(!is_back) wait(NULL);
	}
}
void AnalyzeCommand(char *arr[],int is_back)
{
	//内置命令
	if(strncmp(arr[0],"cd",2)==0)
	{
		MyCdCommand(arr[1]);
        return;
	}
	else if(strncmp(arr[0],"exit",4)==0) exit(0);
	else {
		DealExec(arr,is_back);
	}

	//其他命令
}

int main()
{
	signal(SIGCHLD,Zombie);
	while(1)
	{
		ShowTagInfo();

		char cmd[STRLEN]={0};
		fgets(cmd,STRLEN-1,stdin);
		cmd[strlen(cmd)-1]=0;

		if(strlen(cmd)==0) continue;

		int is_back=0;
		for(int i=0;i<strlen(cmd);i++)
		{
			if(cmd[i]=='&')
			{
				is_back=1;
				cmd[i]=' ';
				break;
			}
		}

		char *arr[STRLEN]={0};
		CutString(cmd,arr);

		AnalyzeCommand(arr,is_back);
	}
}

完成shell:

ls.c中:

在这里插入图片描述

扫描目录:即让shell做一次表达式的通配符扩展,与目录操作有关的函数在dirent.h头文件中。它使用一个名为dir的结构作为目录操作的基础,DIR* 就是一个指向这个结构的目录流指针,就和文件操作那的FILE*类似。

DIR* opendir(const char *path);//返回一个目录流

struct dirent * readdir(DIR *dirp);//返回目录流dirp中下一个目录项的数据,读完了就返回null

int close(DIR *dirp);//关闭掉

在这里插入图片描述

su.c实现:

在这里插入图片描述

流程:

在这里插入图片描述

有待完成:shell几个.文件…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值