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 =='\n' && count < MAXBUF)
{
inpbuf[count] = '\0';
return(count);
}
/* 如果行过长重新输入 */
if (c == '\n')
{
printf("smallsh:input line too long\n");
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=='\t';ptr++)
{
*tok++ = *ptr;
} switch(*ptr++)
{
case '\n':
type=EOL;
break;
case '&':
type=AMPERSAND;
break;
case ';':
type=SEMICOLON;
break;
default:
type=ARG;
while (inarg(*ptr))
{
*tok++ = *ptr++;
} }
*tok++ = '\0';
return (type);
}
step3:采用函数inarg用于确定一个字符是否可以作为参数的组成符,检查字符是否是smallsh的特殊字符,代码如下
static char special[]={‘‘,’\t’,’*’,’;’,’\n’,’\0’};
int inarg(char c)
{
char *wrk;
for (wrk = special;*wrk != ’\0’;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]\n",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();
}
}
Linux网络编程学习(三) ----- 进程控制实例(第三章)的更多相关文章
- Linux网络编程学习(二) ----- 进程控制(第三章)
1.进程和程序 程序是一个可执行文件,而一个进程是一个执行中的程序实例.一个进程对应于一个程序的执行,进程是动态的,程序是静态的,多个进程可以并发执行同一个程序.比如几个用户可以同时运行一个编辑程序, ...
- Linux网络编程学习(八) ----- 文件和记录锁定(第四章)
1.什么是文件和记录锁定? 文件锁定的是整个文件,而记录锁定只锁定文件的一部分,文件和记录锁分为咨询式锁定和强制锁定 1)咨询式锁定 某个进程对某个文件进行了咨询式锁定,其他想访问该文件的进程将会被操 ...
- Linux网络编程学习计划
由于网络编程是很重要的一块,自己这一块也比较欠缺,只知道一些皮毛,从今天开始系统学习<Linux网络编程>一书,全书分为十四个章节: 第一章 概论 P1-16 第二章 UNIX ...
- Linux网络编程学习路线
转载自:https://blog.csdn.net/lianghe_work/article 一.网络应用层编程 1.Linux网络编程01——网络协议入门 2.Linux网络编程02——无连接和 ...
- Linux网络编程——原始套接字实例:MAC 头部报文分析
通过<Linux网络编程——原始套接字编程>得知,我们可以通过原始套接字以及 recvfrom( ) 可以获取链路层的数据包,那我们接收的链路层数据包到底长什么样的呢? 链路层封包格式 M ...
- Linux网络编程学习(四) -----守护进程的建立(第三章)
本文介绍一个例程daemon_init() #include <sys/types.h> #include <signal.h> #include <unistd.h&g ...
- Linux网络编程学习(九) ----- 消息队列(第四章)
1.System V IPC System V中引入的几种新的进程间通信方式,消息队列,信号量和共享内存,统称为System V IPC,其具体实例在内核中是以对象的形式出现的,称为IPC 对象,每个 ...
- linux网络编程学习笔记之五 -----并发机制与线程�
进程线程分配方式 简述下常见的进程和线程分配方式:(好吧,我仅仅是举几个样例作为笔记...并发的水太深了,不敢妄谈...) 1.进程线程预分配 简言之,当I/O开销大于计算开销且并发量较大时,为了节省 ...
- linux网络编程学习笔记之四 -----多-threaded服务器
对于使用过程中并发.通过实现更轻量级线程. 每个线程都是一个独立的逻辑流. 主题是CPU在执行调度的最小独立单位,这个过程是资源分配单元.当然,这是在微内核操作系统说.总之,这是唯一的一个操作系统内核 ...
随机推荐
- JS查看IOS手机的版本号
微信弹portal连接wifi的开发过程中,遇到了有些版本的ios系统在弹portal的浏览器(以下称小浏览器)中无法进行alert(),weixin://等等操作,只能使用window.locati ...
- RSA加密解密实现(JAVA)
1.关于RSA算法的原理解析参考:http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html 2.RSA密钥长度.明文长度和密 ...
- canvas 绘画随机点
直接看图吧: 这样的随机点,是小圆点组成的,然后一直在动,记录一下,万一以后要用到呢: canvas的具体设置我就不写了,另一篇文档里有: drawRandomDot () { let leftCan ...
- Power Query Advanced Editor键盘快捷键
当你点击阅读这篇文章,第一眼看到这首图,是不是不太明白?实际上是小悦对Power BI 功能的12月更新的部分功能很有兴趣,所以今天想用这张张首图作为例,延伸测试键盘快捷键的简单应用,还真别说,确实还 ...
- c++ 11 移动语义
C++ 已经拥有了拷贝构造函数, 和赋值函数,它们主要定位为浅和深度拷贝, 新增加一个移动构造函数,主要避免拷贝构造. 在定义了移动构造函数的情况下,在实参(argument)是一个右值(rvalue ...
- windows环境下安装Python的Rtree包
Rtree包是基于libspatialindex开发的,在安装Rtree之前必须先安装libspatialindex.关于libspatialindex,除了官网的英文外,这里有一个中文翻译过来的介绍 ...
- Linux跨服务器发送文件
在要发送的文件所在的目录下,输入下列命令 第一种: scp -r test.jar root@127.0.0.1:$(pwd)/test.jar 其中root为服务器账户名,127.0.0.1为要发送 ...
- SQL-记录创建篇-006
创建记录: 自己添加记录: insert into table_name values(12,'张三',22) , values(1,'王五',32) insert into table_name(n ...
- struts2多文件上传-2
<!-- 多文件上传 --> <action name="UploadAction2_*" class="uploadfile.UploadAction ...
- python 连接 oracle 统计指定表格所有字段的缺失值数
python连接oracle -- qlalchemy import cx_Oracle as co import pandas as pd from sqlalchemy import crea ...