第一个实例重点说明fork和exec系统函数

该实例是一个交互式命令处理程序,它能完成Linux系统标准Shell的小部分功能,具体功能如下所述:

1.提交命令的参数最多为8个

2.可前,后台执行

3.一命令行中可同时拥有多个命令,彼此之间用分号隔开


实现程序的主流程如下:

for(;;)

{

output("mini_SH-->");

readcmd();

docommand();

}


下面给出源代码:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>#define MAXARG 10
#define LINSIZ 80
#define CMDSIZ 8extern char **environ;
char *quit="quit.quit";
char cmdbuf[CMDSIZ][LINSIZ];
int cmdflag[CMDSIZ];int main()
{int i;for( ; ;){printf("mini_SH-->");for(i=7;i>=0;i--){cmdflag[i]=0;            /* */cmdbuf[i][0]='\0';}if(i=readcmd())             /* */docommand(i);          /* */elseprintf("read command failed, try again!!!\n");}
}readcmd()
{char c,*p;int i=0;p=cmdbuf[0];while((c=getchar())!='\n'){if(c==';'){*p='\0';if(++i==6)return(++i);p=cmdbuf[i];}else if(c=='&'){cmdflag[i]=1;}else*p++=c;}*p='\0';return(++i);
}docommand(int i)
{int j, stat, pid;char *argl[MAXARG], args[LINSIZ];char c, *argsp, **arglp, *p;for(j=0;j<i;j++){arglp=argl;argsp=args;p=cmdbuf[j];while((c=*p++)!='\0'){while(c==' '|| c=='\t')c=*p++;if(c=='\0'){*argsp++='\0';break;}*arglp++=argsp;while(c!=' '&&c!='\t'&&c!='\0'){*argsp++=c;c=*p;if(c)  p++;}*argsp++='\0';}*arglp=(char *)0;if(strcmp(argl[0],quit)==0){printf("Bye Bye!\n");exit(0);}if((pid=fork())==0){if(cmdflag[j]) setpgrp();execve(argl[0],argl,environ);printf("Returned from execve: %s\n",cmdbuf[i]);exit(10);}else{if(! cmdflag[j])while(wait(&stat)!=pid);}}}

程序代码说明:

(1) 数据结构说明。该mini_SH定义了每条命令所能使用的最大参数个数为MAXARG,定义为10。每条命令的字符缓存数组由LINSIZ决定,最大为80,一次提交的命令个数由CMDSIZ决定,最多8个。字符指针quit存放退出命令字符串,它已经赋值为quit.quit,二维数组cmdbuf存放标准输入读到的字符串,而数组cmdflag决定该命令以何种方式执行,0为前台,1为后台。

(2)main函数。按主流程的设计思想实现,在无限循环for中,首先打印命令接收提示符mini_SH-->,将用户输入的命令字符串,通过函数readcmd得到并存储在cmdbuf二维数组中,readcmd返回一次提交的用分号隔开的命令个数。而函数docommand执行存放在cmdbuf中的命令。

(3)readcmd函数。将用户从标准输入提交的一行命令,按分号为界,分别存放命令缓冲区cmdbuf中,如果命令字符中有“&”符,将命令标志数组cmdflag的相应位置为1,每次提交命令时,该数组字段被清为0,并返回提交的命令个数。

(4)docommand函数。在for循环中,每次执行一条命令。用户提交的命令按顺序存放在数组cmdbuf中,while循环将命令执行的参数以空格或制表符为分界线,将字符型的指针数组argl分别指向相应的字符串,argl[0]指向该命令字符串,arg[1]是该命令的第一个参数,以此类推,最后一个参数为空指针。对于每一个参数增加一个空字符”\0“。如果命令字符串为定义的退出该命令字符串quit.quit,则调用exit系统函数退出执行,否则,调用fork生成子进程。如果设置后台标志位,则重新设置进程组号,使用带环境变量的系统调用execve执行用户提交用户执行的命令,如该命令以后台方式执行,则父进程不等待该命令执行完后就可执行新的命令。否则,父进程使用wait函数等待子进程执行暂停或终止。


该程序是一个完整的程序,编译后生成mini_sh命令,一下是在mini_sh命令控制下,用户提交命令的执行情况:

$ ./mini_sh

mini_SH-->/bin/date

2011年12月05日 星期一 23:37:19 PST

mini_SH-->/bin/who

Returned from execve:

mini_SH-->/bin/pwd;/bin/date

/home/lxy/test1/BruceZhang

2011年12月05日 星期一 23:37:19 PST

mini_SH-->quit.quit

Bye Bye!

Linux C编程--进程介绍7--综合应用实例相关推荐

  1. Linux C编程--进程介绍1--进程的创建

    这篇文章介绍的内容包括 1.Linux进程--进程标识号 2.进程控制--进程创建 1.Linux进程--进程标识号 进程(Process)是一个程序在其自身的虚拟地址空间中的一次执行活动.多个程序并 ...

  2. Linux C编程--进程介绍6--进程的各种标识

    本文将介绍进程的: 1.进程的用户标识号 2.进程标识号 进程的用户ID     Linux/Unix进程涉及到三类用户ID:       1.实际用户ID(real user id,RUID):为该 ...

  3. Linux C编程--进程介绍3--进程终止和等待

    进程结束 1.在Linux中任何让一个进程结束 进程退出表示进程即将结束.在Linux中进程退出分为了正常退出和异常退出两种. 1>正常退出 a. 在main()函数中执行return . b. ...

  4. Linux C编程--进程介绍4--errno

    当linux中的C api函数发生异常时,一般会将errno变量(需includeerrno.h)赋一个整数值,不同的值表示不同的含义,可以通过查看该值推测出错的原因,在实际编程中用这一招解决了不少原 ...

  5. Linux C编程--进程介绍5--system函数

    表头文件 #i nclude<stdlib.h> 定义函数 int system(const char * string); 这个函数是用fork,exec,waitpid这三个系统函数实 ...

  6. Linux C编程--进程介绍2--exec函数

    exec函数族 fork()函数是用于创建一个子进程,该子进程几乎拷贝了父进程的全部内容,但是,这个新创建的进程如何执行呢?这个exec函数族就提供了一个在进程中启动另一个程序执行的方法.  exec ...

  7. Linux 系统编程 -进程概念篇

    Linux系统编程-进程篇 冯诺依曼体系结构 冯诺依曼的两个重要思想 当代计算机的三级缓存 操作系统 操作系统的概念 操作系统的组成 操作系统作用 Linux下的操作系统体系 进程 进程概念 进程特性 ...

  8. Linux系统编程——进程基础知识

    Linux系统编程--进程基础知识 1.程序和进程 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu.内存.打开的文件.设备.锁-) 进程,是一个抽象的概念,与操作系统原理联系紧密.进程 ...

  9. Linux系统编程 进程控制

    文章目录 01. 学习目标 02. 进程和程序 (理解) 03. 单道.多道程序设计(了解) 3.1 单道程序设计 3.2 多道程序设计 04. 并行和并发(理解) 05. MMU(了解) 06. 进 ...

最新文章

  1. Tomaso Poggio:深度学习需要从炼金术走向化学
  2. 深度解析 PouchContainer 的富容器技术
  3. Material Designer的低版本兼容实现(十)—— CheckBox RadioButton
  4. centos下fail2ban安装与配置详解
  5. 数据科学环境Anaconda及其相关组件介绍
  6. Qt Widgets、QML、Qt Quick的概念与区别
  7. 【无码专区6】球与盒子(数学线性筛)
  8. linux 关闭桌面环境,Ubuntu 14.04上的Cinnamon桌面环境PPA被关闭
  9. Maven高级之插件开发
  10. vue中使用高德地图 amap--基础使用方法
  11. 20 年前,微软怎样改变了我们鼠标的使用方式?| 极客头条
  12. 蜘蛛侠3.1(无错版)站群分享源码 带视频,关键字软件安装使用教程
  13. 更改重做日志(redolog)文件的大小
  14. nginx的日志格式
  15. oracle跨库连接查询
  16. Nginx的配置使用,启动、重启、关闭,以及路径配置
  17. matlab 线性拟合相关系数,Matlab拟合非线性曲线后求相关系数(拟合的优劣)
  18. 前端Docker教程
  19. 骑士cms(74cms)个人版 整合UC
  20. 解构华为AI技术布局:构建无所不及的智能

热门文章

  1. 学习虚幻4需要储备的知识(2D游戏开发者向)
  2. SharePoint中的列表(List) 与Content Type 之五
  3. oracle修改机器名后不能启动Console的解决方案
  4. oracle表分区详解
  5. 我要放弃RedHat Linux了
  6. Redis进阶实践之五Redis的高级特性
  7. 资管机构年中规模排名出炉:中信资管规模超万亿
  8. httpd中工作模型的比较
  9. 【运维囧事】事先没想到客户光驱坏了,主要原因还是自己当初经验不足
  10. 最爱莫乎生命,其次是“你”