• Linux网络编程学习(三) ----- 进程控制实例(第三章)


    本节主要介绍一个进程控制的实例,功能就是在前台或者后台接收命令并执行命令,还能处理由若干个命令组成的命令行,该程序命名为samllsh。

    基本逻辑就是

    while(EOF not typed)
    {
         从用户终端取得命令行
         执行命令  
    }
    

    setp1:取得命令行内容,用uerin函数实现,处理步骤首先显示提示符,提示符的具体内容由用户通过参数传递给函数,然后每次从键盘读取一个字符,存入inpbuf中,结束时userin返回字符个数或者EOF(文件结尾),换行符也要存入inpbuf

    代码如下:

    #include "smallsh.h"
    /* 程序缓冲区和指针 */
    static char inpbuf[MAXBUF],tokbuf[2*MAXBUF],
    *ptr = inpbuf,*tok = tokbuf;
    /* userin()函数 */
    int userin(chat* p)
    {
    	int c,count;
    	ptr = inpbuf;
    	tok = tokbuf;
    	/* 显示提示 */
    	printf("%s ",p);
    	for (count = 0;;) 
    	{
    		if ((c=getchar())==EOF)
    		return(EOF);
    		if (count < MAXBUF)
    		inpbuf[count++] = c;
    		if (c =='
    ' && count < MAXBUF) 
    		{
    			inpbuf[count] = '';
    			return(count);
    		}
    		/* 如果行过长重新输入 */
    		if (c == '
    ') 
    		{
    			printf("smallsh:input line too long
    ");
    			count=0;
    			printf("%s ",p);
    		}
    	}
    }
    

      其中的头文件samllsh.h内容为

    #include <stdio.h>
    #define EOL 1 /* 行结束 */
    #define ARG 2
    #define AMPERSAND 3
    #define SEMICOLON 4
    #define MAXARG 512 /* 命令行参数个数的最大值 */
    #define MAXBUF 512 /* 输入行的最大长度 */
    #define FOREGROUND 0
    #define BACKGROUND 1
    

      step2:从userin构造的命令行缓冲区中分析出命令名和参数,采用gettok函数,其中的tptr是一个字符型指针,调用后该指针指向实际的解析出的内容,调用方法是toktype = gettok(&tptr)

    int gettok(char* output)
    {
    	int type;
    	outptr = tok;
    	/* 首先去除空白字符 */
    	for (;*ptr==''||*ptr=='	';ptr++)
    	{
    		*tok++ = *ptr;	
    	}
    		
    	switch(*ptr++) 
    	{
    		case '
    ':
    		type=EOL;
    		break;
    		case '&':
    		type=AMPERSAND;
    		break;
    		case ';':
    		type=SEMICOLON;
    		break;
    		default:
    		type=ARG;
    		while (inarg(*ptr))
    		{
    			*tok++ = *ptr++;
    		}
    		
    	}
    	*tok++ = '';
    	return (type);
    }
    

      step3:采用函数inarg用于确定一个字符是否可以作为参数的组成符,检查字符是否是smallsh的特殊字符,代码如下

    static char special[]={‘‘,’	’,’*’,’;’,’
    ’,’’};
    int inarg(char c)
    {
    	char *wrk;
    	for (wrk = special;*wrk != ’’;wrk++)
    	{
    		if (c == *wrk)  return(0);
    	}	
    	return(1);
    }
    

      step4:程序procline使用函数gettok()分析命令行,处理过程中构造一张参数表,当遇到换行符或者分号时,就调用runcommand来执行被分析的命令行,假设已经用userin读入了一个输入行

    #include "smallsh.h"
    void procline()
    {
    	char * arg[MAXARG+1];
    	int toktype;
    	int narg;
    	int type;
    	for(narg = 0;;) 
    	{
    		switch(toktype = gettok(&arg[narg])) 
    		{
    			case ARG:
    			if (narg<MAXARG)
    			narg++;
    			break:
    			case EOL:
    			case SEMICOLON:
    			case AMPERSAND:
    			type = (toktype==AMPERSAND)?BACKGROUND:FOREGROUND;
    			if (narg != 0) 
    			{
    				arg[narg] = NULL;
    				runcommand(arg,type);
    			}
    			if (toktype==EOL)
    				return;
    			narg=0;
    			break;
    		}
    	}
    }
    

      step5:函数runcommand,实现启动命令进程,入参为一个整型参数where,如果where被设置为BACKGROUND,那么将忽略wait()的调用,并且runcommand只显示进程标识符就返回。wait()返回的是第一个结束的子进程的进程标识符,而不是最后一个被启动的子进程的进程标识符。

    execvp()表明按当前环境变量Path中的目录来搜索命令中表明的程序文件

    #include "smallsh.h"
    int runcommand(char** cline,int where)
    {
    	int pid,exitstat,ret;
    	if((pid = fork()) < 0) 
    	{
    		perror("fork fail");
    		return(-1);
    	}
    	if (!pid) 
    	{ /* 子进程代码 */
    		execvp(*cline,cline);
    		perror(*cline);
    		exit(127);
    	}
    	/* 父进程代码 */
    	/* 后台进程代码 */
    	if (where==BACKGROUND) 
    	{
    		printf("[process id %d]
    ",pid);
    		return(0);
    	}
    	/* 前台进程代码 */
    	while ((ret = wait(&exitstat))!= pid && ret != -1) ;
    	return (ret==-1?-1:exitstat);
    }
    

      step6:最后就是main函数了

    #include "smallsh.h"
    char *prompt = "command>";
    void main()
    {
    	while (userin(prompt)!=EOF)
    	{
    		procline();
    	}
    }
    

      

  • 相关阅读:
    硬件的效率与一致性
    深入理解SPI机制-服务发现机制
    spring 之7种重要设计模式
    list里放map list 放list
    jvm 三种编译
    几种不同格式的json解析
    Java知识点梳理——集合
    判断2个list中是否有相同的数据(相交)Collections.disjoint
    键相同,比较两个map中的值是否相同
    Map类型数据导出Excel--poi
  • 原文地址:https://www.cnblogs.com/xqn2017/p/8886195.html
Copyright © 2020-2023  润新知