linux入门:编写一个简单的shell(仅支持部分ls,ps命令)
2015-04-21 15:55
781 查看
实验要求:
编写一个最基本的shell服务,实现基本的类ls和类ps命令。
实验结果:
一个简单的shell
识别命令:
ls
ls(地址)
不输出隐藏文件夹/文件
ls-a (地址)
输出隐藏文件夹/文件
//可识别地址中的“~”
ps
输出为ps-A的结果
q
退出
源文件:
shell
-----src
---shell.c//含main与main_loop函数,对输入进行识别判断,调用其它函数进行处理。
---ls.c//含cmd_ls及相关函数
---ps.c//含cmd_ps及相关函数
-----include
---shell.h//包含所有所需的头文件
---ls.h//供调用cmd_ls
---ps.h//含有一个结构体procinfo,对应/proc/%d/stat文件的内容,这一结构体来源于互联网资源。
源代码:
编写一个最基本的shell服务,实现基本的类ls和类ps命令。
实验结果:
一个简单的shell
识别命令:
ls
ls(地址)
不输出隐藏文件夹/文件
ls-a (地址)
输出隐藏文件夹/文件
//可识别地址中的“~”
ps
输出为ps-A的结果
q
退出
源文件:
shell
-----src
---shell.c//含main与main_loop函数,对输入进行识别判断,调用其它函数进行处理。
---ls.c//含cmd_ls及相关函数
---ps.c//含cmd_ps及相关函数
-----include
---shell.h//包含所有所需的头文件
---ls.h//供调用cmd_ls
---ps.h//含有一个结构体procinfo,对应/proc/%d/stat文件的内容,这一结构体来源于互联网资源。
源代码:
//<src>部分 //shell.c #include"shell.h" //主循环,读入并解析指令 intmain_loop() { charcmd[100]; while(1){ printf(">"); fgets(cmd,40,stdin); intsize=strlen(cmd); cmd[size-1]='\0'; char*p=strtok(cmd," "); if(strcmp(p,"ls")==0){ p=strtok(NULL,""); if(p==NULL) cmd_ls(".",0); else if(strcmp(p,"-a")==0){ p=strtok(NULL,""); if(p==NULL) cmd_ls(".",1); elsecmd_ls(p,1); } elsecmd_ls(p,0); }else if(strcmp(p,"ps")==0){ cmd_ps(); } elseif(strcmp(p,"q")==0) break; elseprintf("command undetected\n"); } return0; } intmain() { printf("welcometo leejf_shell!\n"); main_loop(); printf("GoodBye! ^_^"); return0; } //ls.c #include"shell.h" intcmd_ls(char *dirname,int type)//遍历目录下的文件及文件及输出名称 { DIR*p_dir; structdirent *p_dirent; //替换目录中的“~” if(dirname[0]=='~'){ structpasswd *pwd; pwd=getpwuid(getuid()); chartmp[100]="/home/"; strcat(tmp,pwd->pw_name); strcat(tmp,dirname+1); dirname=tmp; } if((p_dir=opendir(dirname))==NULL){ fprintf(stderr,"---->can\'topen %s\n",dirname); return0; } //遍历文件与文件夹 while((p_dirent=readdir(p_dir))){ char*tmp=p_dirent->d_name; if(!strcmp(tmp,".")||!strcmp(tmp,"..")) continue; if(type==0&&tmp[0]=='.') continue; printf("%s\n",tmp); } closedir(p_dir); return1; } //ps.c #include"shell.h" #include"ps.h" intdigit(char *name)//判断文件名是否为数字 { intsize,i; size=strlen(name); if(size==0)return 0; for(i=0;i<size;i++) if(name[i]<'0'||name[i]>'9')return 0; return1; } voidgetinfo(char *name,procinfo *pinfo)//对一个进程的stat文件,读取其中的信息。 //这部分做得很完整。然而输出时只输出了极少的信息。可扩 //展的地方很多 { chardir[_POSIX_PATH_MAX],stat[4096]; sprintf(dir,"/proc/%s/stat",name); FILE*fp=fopen(dir,"r"); fgets(stat,4096,fp); sscanf(stat,"%d",&(pinfo->pid)); char*s,*t; s=strchr(stat,'(')+1; t=strchr(stat,')'); strncpy(pinfo->exName,s,t-s); pinfo->exName[t-s]='\0'; sscanf(t + 2, "%c %d %d %d %d %d %u %u %u %u %u %d %d %d %d %d %d %u%u %d %u %u %u %u %u %u %u %u %d %d %d %d %u", /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33*/ &(pinfo->state), &(pinfo->ppid), &(pinfo->pgrp), &(pinfo->session), &(pinfo->tty), &(pinfo->tpgid), &(pinfo->flags), &(pinfo->minflt), &(pinfo->cminflt), &(pinfo->majflt), &(pinfo->cmajflt), &(pinfo->utime), &(pinfo->stime), &(pinfo->cutime), &(pinfo->cstime), &(pinfo->counter), &(pinfo->priority), &(pinfo->timeout), &(pinfo->itrealvalue), &(pinfo->starttime), &(pinfo->vsize), &(pinfo->rss), &(pinfo->rlim), &(pinfo->startcode), &(pinfo->endcode), &(pinfo->startstack), &(pinfo->kstkesp), &(pinfo->kstkeip), &(pinfo->signal), &(pinfo->blocked), &(pinfo->sigignore), &(pinfo->sigcatch), &(pinfo->wchan)); } intcmd_ps()//执行ps指令。遍历/proc目录下的所有文件,对文件夹名为数字的,读取目录下的stat文 //件,解析并输出部分信息 { printf(" PID TTY TIME CMD\n"); DIR*proc=opendir("/proc"); structdirent *p_dirent; while((p_dirent=readdir(proc))){ char*name=p_dirent->d_name; if(digit(name)){ procinfopinfo; getinfo(name,&pinfo); charctty[10],ctime[10]; if(pinfo.tty<=1031&&pinfo.tty>1024) sprintf(ctty,"tty%d",(pinfo.tty-1024)); else if(pinfo.tty>34816) sprintf(ctty,"pts/%d",pinfo.tty-34816); else{ ctty[0]='?'; ctty[1]='\0'; } sprintf(ctime,"%2d:%2d:%2d",pinfo.utime/360000,(pinfo.utime/6000)%60,(pinfo.utime/100)%60); printf("%5d%-8s %8s %s\n",pinfo.pid,ctty,ctime,pinfo.exName); } } return0; } //<include>部分 //shell.h #ifndefSHELL #defineSHELL #include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<fcntl.h> #include<dirent.h> #include<string.h> #include<linux/sched.h> #include<errno.h> #include<pwd.h> #include"ls.h" #include"ps.h" #endif //ps.h #ifndefPS_H_INCLUDED #definePS_H_INCLUDED typedefstruct statstruct_proc { int pid; /** The process id. **/ char exName [_POSIX_PATH_MAX]; /** The filename of the executable**/ char state; /** 1 **/ /** R is running, S is sleeping, D is sleeping in an uninterruptible wait, Z is zombie, T is traced or stopped **/ unsigned euid, /** effective user id **/ egid; /** effective group id */ int ppid; /** The pid of the parent. **/ int pgrp; /** The pgrp of the process. **/ int session; /** The session id of theprocess. **/ int tty; /** The tty the process uses **/ int tpgid; /** (too long) **/ unsignedint flags; /** The flags of the process. **/ unsignedint minflt; /** The number of minor faults **/ unsignedint cminflt; /** The number of minor faults withchilds **/ unsignedint majflt; /** The number of major faults **/ unsignedint cmajflt; /** The number of major faults withchilds **/ int utime; /** user mode jiffies **/ int stime; /** kernel mode jiffies **/ int cutime; /** user mode jiffies with childs **/ int cstime; /** kernel mode jiffies withchilds **/ int counter; /** process's next timeslice **/ int priority; /** the standard nice value, plusfifteen **/ unsignedint timeout; /** The time in jiffies of the nexttimeout **/ unsignedint itrealvalue; /** The time before the next SIGALRMis sent to the process **/ int starttime; /** 20 **/ /** Time the process startedafter system boot **/ unsignedint vsize; /** Virtual memory size **/ unsignedint rss; /** Resident Set Size **/ unsignedint rlim; /** Current limit in bytes on the rss**/ unsignedint startcode; /** The address above which programtext can run **/ unsignedint endcode; /** The address below which programtext can run **/ unsignedint startstack; /** The address of the start of thestack **/ unsignedint kstkesp; /** The current value of ESP **/ unsignedint kstkeip; /** The current value of EIP **/ int signal; /** The bitmap of pending signals **/ int blocked; /** 30 **/ /** The bitmap of blocked signals**/ int sigignore; /** The bitmap of ignored signals**/ int sigcatch; /** The bitmap of catched signals**/ unsignedint wchan; /** 33 **/ /** (too long) **/ int sched, /** scheduler **/ sched_priority; /** scheduler priority **/ }procinfo; intcmd_ps(); #endif// PS_H_INCLUDED //ls.h #ifndefLS_H_INCLUDED #defineLS_H_INCLUDED intcmd_ls(char *dirname,int type); #endif// LS_H_INCLUDED
相关文章推荐
- Linux常用shell命令——想到一个记一个,都是菜鸟入门命令
- 用C语言编写一个Linux下的简单shell程序
- linux入门 ls命令编写之一------ls1
- linux入门 ls命令编写之二------ls2:列对齐输出
- shell脚本入门---编写一个简单的脚本(批处理)
- 一天一个shell命令 linux好管家-进程-ps命令详解
- 一天一个shell命令 linux好管家-进程-ps命令详解
- linux简单命令--shell入门命令
- 编写自己的shell解析器(一)一个简单的循环命令输入和历史打印
- 用C语言编写一个Linux下的简单shell程序
- 一个简单的linux命令——ls
- 操作系统实验参考以上示例程序中建立并发进程的方法,编写一个多进程并发执行程序。父进 程首先创建一个执行ls命令的子进程然后再创建一个执行ps命令的子进程,并控制 ps 命令总在 ls 命令之前执行。
- 【linux】编写一个简单的shell
- 编写一个SHELL脚本,可以获得指定目录下的所有文件及文件夹的大小。输出的样式与 ls -lh 命令相同。
- linux中新增一个shell命令最简单的方法
- 每天一个linux命令(41):ps命令
- 每天一个linux命令(1):ls命令
- 一个工作几年的linux运维工程师积累下来工作中常用的命令集合(shell)
- 【每天一个linux命令】ls
- 【Linux】实现一个简单的shell