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在执行调度的最小独立单位,这个过程是资源分配单元.当然,这是在微内核操作系统说.总之,这是唯一的一个操作系统内核 ...
随机推荐
- 什么是Maven项目
1.通俗理解Maven:https://blog.csdn.net/shuzhe66/article/details/45009175 个人总结: Maven项目会有pom文件! 当前的项目需要依赖其 ...
- 强大的拖拽组件:React DnD 的使用
强大的拖拽组件:React DnD 的使用 react.js 10.6k 次阅读 · 读完需要 25 分钟 17 文章首发我的个人blog : 原文链接 学习 React DnD 的最初原因是阅读 ...
- WEBBASE篇: 第八篇, JavaScript知识2
JavaScript 2 一,数据类型: 作用: 约束了数据在内存中所占空间大小问题的: JS数据类型分类: 基本数据类型(值类型) (1) number 类型: 数字类型,可以表示32位的整数或64 ...
- MySql之左连接,右连接
左连接,右连接查询的表 中 on后面的条件不会影响主表的数据,只会影响右表的数据. 例: 没加条件的时候 左表加条件: 右表加条件: 通过上面3处对比可以看出来,用LEFT JOIN 的时候不管对左表 ...
- bash的工作特性(2)
bash的工作特性之命令执行状态返回值和命令行展开所涉及的内容及其示例演示. 命令的执行结果状态 成功,失败 bash使用特殊变量$?保存最近一条命令的执行状态结果:echo$? 0:成功 1-255 ...
- 《Linux内核原理与分析》第九周作业
课本:第八章 进程的切换和系统的一般执行过程 进行进程调度的时机 Linux内核通过schedule函数实现进程调度,schedule函数在运行队列中找到一个进程,把CPU分配给它 调用schedul ...
- 数组排序自定义comparator()
案例1:现在有一个普通数组arr = [3,1,2,4,5,6,8,0,1]; 自定义一个排序方法: function createComparator(){ return function (obj ...
- Java BigInterger类
BigInteger概述 可以让超过Integer范围内的数据进行运算 构造方法 public BigInteger(String val) 成员方法 public BigInteger add(Bi ...
- C-Language Functions
转自:https://www.postgresql.org/docs/9.6/xfunc-c.html 可以作为学习基于c编写pg extension 的资料 36.9. C-Language Fun ...
- Scala环境(集成idea)
1 语言介绍 他已经出生15年了,就像明星一样,谁都不可能一开始就人气爆棚粉丝无数,得慢慢混. 据说这家伙已经威胁到了Java的地位,我当时也是被这句话惊到,才毅然决然的认识了他.目前也正在努力学习中 ...