第8章 进程和程序:编写命令解释器sh

进程

 在Unix术语中,一个可执行程序是一个机器指令及其数据的序列每一个进程是程序运行时的内存空间和设置。可以用ps命令查看进程。
 每个进程都有一个唯一的进程id,所有者,大小以及其他属性
 系统进程中的很大一部分是没用终端与之相连的,它们在系统启动时启动,而不是由用户在命令行输入。
 内存可以看作是一个容纳内核和进程的空间。Unix中的内存分为系统空间和用户空间,进程存在与用户空间。内存实际上就是一个字节序列,或者很大的数组,如果机器有64MB的内存,就意味着这个数组大概有6700万个内存位置。
 建立一个进程有点像建立一个磁盘文件。内核要找到一些用来存放程序指令和数据的空闲内存页。内核还要建立数据结构来存放相应的内存分配情况和进程属性。

shell:进程控制和程序控制的一个工具

●三个功能
1.运行程序
shell将ls,date这些程序载入内存并运行,类似于程序启动器
2.管理输入和输出
可以使用<,>,和|将输入输出重定向,这样就可以告诉shell将进程的输入输出连接到一个文件或是其他的进程。
3.编程
shell同时也是带有变量和流程控制的编程语言。

●如何运行程序
在这里插入图片描述
在这里插入图片描述

●编写shell需要学会的问题
1.运行一个程序
在这里插入图片描述
在这里插入图片描述
 exec传递的参数必须是字符串,因为进程间通信的参数类型为字符串。
 execvp/exit就像call/return,这种通过参数和返回值在拥有私有数据的函数间通信的模式是结构化程序设计的基础。
在这里插入图片描述
 调用execvp的话运行完进程会退出,而shell应该运行完继续等待下一个命令,解决方法就是新建一个进程,由这个进程来执行命令程序。

2.建立一个进程
 fork在子进程中返回0,在父进程中fork返回进程子进程pid,新的进程从fork返回的地方开始运行,而不是从头开始运行。
在这里插入图片描述
在这里插入图片描述

3.等待exit()
(1)wait阻塞调用它的程序直到子进程结束
(2)wait返回结束进程的PID,还可以将一个描述退出方式的整数保存在传入wait的整型变量地址中。
在这里插入图片描述
在这里插入图片描述
exit
在这里插入图片描述
在这里插入图片描述

实现一个shell

在这里插入图片描述

#include<stdio.h>
#include<signal.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/types.h>
#include<sys/wait.h>
#define MAXARGS 20	//最多参数个数
#define ARGLEN 100	//参数长度

void execute(char **);

int main()
{
	char *arglist[MAXARGS+1];	//arglist[n]为字符串参数的首地址
	int numargs=0;	//数组的序号	
	char argbuf[ARGLEN];
	char *makestring();
	while(numargs<MAXARGS)
	{
		printf("Arg[%d]?",numargs);
		if(fgets(argbuf,ARGLEN,stdin)&&*argbuf!='\n')	//如果获取到了参数
			arglist[numargs++]=makestring(argbuf);	//参数地址存入列表
		else{
			if(numargs>0){
				arglist[numargs]=NULL;	//结束参数的输入,最后位置NULL
				execute(arglist);	//执行
				numargs=0;	//重置
			}
		}
	}
	return 0;
}
void execute(char *arglist[])
{
	int pid,exitstatus;	//保存进程id以及推出原因
	pid=fork();
	switch(pid){
		case -1:
			perror("fork failed");
			exit(1);
		case 0:		//子进程执行
			execvp(arglist[0],arglist);	//执行execvp,将子进程原程序覆盖
			perror("execvp failed");//如果执行到这,说明execvp失败了
			exit(1);
		default:	//父进程执行
			while(wait(&exitstatus)!=pid)	//等待子进程结束
				;
			printf("child exited with status %d,%d\n",
					exitstatus>>8,exitstatus&0377);
	}
}
char *makestring(char *buf)	//将argbuf转为字符串并返回参数存储的地址
{
	char *cp;
	buf[strlen(buf)-1]='\0';	//加'\0'形成字符串
	cp=malloc(strlen(buf)+1);
	if(cp==NULL){
		fprintf(stderr,"no memory\n");
		exit(1);
	}
	strcpy(cp,buf);
	return cp;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值