1.C++实现ls命令

  1. #include<dirent.h>
  2. #include<stdlib.h>
  3. #include<iostream>
  4. #include "apue.h"
  5. using namespace std;
  6. int main(int argc,char * argv[]){
  7. DIR *d
  8. struct dirent *dirp;
  9. if(argc!=2){
  10. cout<<"usage: ls directory_name"<<endl;
  11. exit(-1);
  12. }
  13. if((dp=opendir(argv[1]))==NULL){
  14. cout<<"can't open "<<argv[1]<<endl;
  15. }
  16. //循环读取目录项
  17. while((dirp=readdir(dp))!=NULL){
  18. //输出文件名称
  19. cout<<dirp->d_name<<endl;
  20. }
  21. closedir(dp);
  22.  
  23. exit(0);
  24. }

opendir函数返回指向DIR结构的指针,我们将该指针传送给readdir函数。在循环中调用 readdir来读取每个目录项。该函数返回指向dirent结构的指针,而当目录中没有目录项可读时返回空指针。然后在循环中输出从dirent结构中 取出的每个目录项的名称。

2.C++ 实现从输出从标准输入中读到的内容

  1. #include "apue.h"
  2. #include<iostream>
  3. using namespace std;
  4. #define BUFFSIZE 4096
  5. int main(){
  6. int n;
  7. //缓冲
  8. char buf[BUFFSIZE];
  9. //从标准输入中读取,缓冲区大小为BUFFSIZE,缓冲区对应buf
  10. while((n=read(STDIN_FILENO,buf,BUFFSIZE))>0){
  11. //向标准输出输出buf中的内容
  12. if(write(STDOUT_FILENO,buf,n)!=n)
  13. cout<<"wirte error"<<endl;
  14. }
  15. //读取标准输入出错
  16. if(n<0)
  17. cout<<"read error"<<endl;
  18. exit(0);
  19. }

运行截图:

3.使用标准I/O实现例2中的内容

  标准I/O函数为那些不带缓冲的I/O函数提供了一个带缓冲的接口。使用标准I/O函数无需担心如何选取最佳的缓冲区大小。

  以下用getc函数与putc函数实现例2中的功能。

  1. #include "apue.h"
  2. #include <iostream>
  3. using namespace std;
  4. int main(){
  5. int c;
  6. while((c=getc(stdin))!=EOF){
  7. if(putc(c,stdout)==EOF)
  8. cout<<"output error"<<endl;
  9. }
  10. if(ferror(stdin))
  11. cout<<"input error"<<endl;
  12.  
  13. return 0;
  14. }

4.输出进程ID

  UNIX确保每个进程都有唯一的数字标识符,成为进程ID。进程ID是一个非负整数。

  下面是一个输出本程序进程ID的 程序代码。

  1. #include "apue.h"
  2. #include <iostream>
  3. using namespace std;
  4. int main(){
  5. cout<<"hello world from process ID"<<getpid()<<endl;
  6. return 0;
  7. }

分别运行两次,输出如下:

hello world from process ID18357

hello world from process ID18385

5.开辟新进程执行输入的命令

  利用C++对标准输入 输入的命令开辟新的进程加以执行。

  1. #include "apue.h"
  2. #include <sys/wait.h>
  3. #include <iostream>
  4. using namespace std;
  5. int main(){
  6. char buf[MAXLINE]; //MAXLINE->4096
  7. pid_t pid;
  8. int status;
  9. cout<<"%% ";/* print prompt (printf requires %% to print %)*/
  10. while(fgets(buf,MAXLINE,stdin)!=NULL){
  11. //fets函数返回的每一行都以换行符结束,后面紧随一个'\0',需要将换行符号替换为'\0'
  12. if(buf[strlen(buf)-1]=='\n')//最后一个字符是换行符
  13. buf[strlen(buf)-1]='\0';//将其替换为结束符号
  14. //调用fork()创建新进程,fork对父进程返回子进程的ID,对子进程返回0.fork调用一次,在父进程和子进程中各调用一次
  15. if((pid=fork())<0){
  16. cout<<"fork error"<<endl;
  17. }else if(pid==0){//成功创建子进程
  18. //在子进程中执行buf对应的命令,
  19. execlp(buf,buf,(char *)0);
  20. cout<<"could't execute: "<<buf<<endl;
  21. exit(127);
  22. }
  23. //父进程等待子进程结束
  24. //waitpid()函数返回子进程的终止状态,保存在status中
  25. /* parent */
  26. if((pid=waitpid(pid,&status,0))<0)
  27. cout<<"wait pid error!"<<endl;
  28. cout<<"%% ";
  29. }
  30.  
  31. return 0;
  32. }

执行过程:

  1. %% ls
  2. b CMakeFiles hello_world Makefile
  3. CMakeCache.txt cmake_install.cmake hello_world.cbp
  4. %% date
  5. 2016 03 20 星期日 23:01:21 CST

  上述程序的重点是函数fork以及函数waitpid。fork创建一个新进程。fork对父进程返回子进程的进程ID(非负整数),对子进程返回0。fork调用一次,对父进程和子进程各返回一次。

  父进程等待子进程终止是通过waitpid实现的,其参数指定要等待的进程(pid指定),返回子进程的终止状态(status变量)。

 6.出错处理

  当Unix系统函数出错的时候,通常会返回一个负值,而且整型变量errno通常被设置为具有特定信息的值。

  文件<errno.h>定义了errno以及可以赋予它的各种变量,这些变量都以E开头。

  C标准定义了两个函数,用于打印出错的信息。

  1. #include<string.h>
  2. char *strerror(int errnum)
  3. //将errnum(errno)映射为一个出错的消息字符串,并且返回这个字符串的指针
  1. #include<stdio.h>
  2. void perror(const char * msg)
  3. //基于当前的errno值,在标准错误上产生一条出错的信息,然后返回。

  以下程序是 使用上述两个函数的案例。

  1. #include<iostream>
  2.  
  3. #include<errno.h>
  4. #include<stdio.h>
  5. #include <string.h>
  6.  
  7. using namespace std;
  8. int main(int argc,char*argv[]){
  9. //将EACCES映射为一个出错消息字符串
  10. fprintf(stderr,"EACCES: %s\n",strerror(EACCES));
  11. errno=ENOENT;
  12. //基于当前errno的值,在标准错误上产生一条出错信息
  13. perror(argv[]);
  14.  
  15. }

7.用户id和组id

  用户id用于标识不同的用户,root用户的用户id为0.组将同属一个项目或者部门的用户集合在一起,他们一般具有相同的权限,可以访问组权限限定的文件。

  以下程序用户获取当前用户的用户id以及组id。

  1. #include<iostream>
  2. #include "apue.h"
  3. using namespace std;
  4. int main(int argc,char*argv[]){
  5. //输出用户id和组id
  6. cout<<"uid="<<getuid()<<",gid= "<<getgid()<<endl;
  7. }

8. 信号

  信号用于通知进程发生了某种情况,例如某一进程执行执行除法操作,其除数为0,则将名为SIGFPE(浮点异常)的信号发送给该进程。进程有以下3种处理信号的方式。

  1.忽略信号。2.按系统默认方式处理。3.提供一个函数,信号发生的时候调用该函数,这被称为捕捉该信号。通过自己定义的程序,我们就知道什么时候产生了信号,并按照期望的方式进行处理。

  实例:捕捉中断键发出的信号。

  1. #include<iostream>
  2. #include "apue.h"
  3. #include <sys/wait.h>
  4. using namespace std;
  5. //用于捕捉信号的函数
  6. static void sig_int(int signo){//信号处理函数,输出Interrupt
  7. cout<<"Interrupt "<<endl;
  8. }
  9. int main(){
  10. char buf[MAXLINE];
  11. pid_t pid;
  12. int status;
  13. if(signal(SIGINT,sig_int)==SIG_ERR)//绑定信号
  14. cout<<"signal error"<<endl;
  15. cout<<"%% ";
  16. while(fgets(buf,MAXLINE,stdin)!=NULL){
  17. if(buf[strlen(buf)-]=='\n')
  18. buf[strlen(buf)-]='\0';
  19. if((pid=fork())<){
  20. cout<<"fork error"<<endl;
  21. }else if(pid==){
  22. execlp(buf,buf,(char *));
  23. cout<<"could't execute :"<<buf<<endl;
  24. exit(-);
  25. }
  26. if((pid=waitpid(pid,&status,))<)
  27. cout<<"wait pid error"<<endl;
  28. cout<<"%% ";
  29. }
  30. return ;
  31. }

运行截图:

  

apue- chapter 1 UNIX基础知识的更多相关文章

  1. 《UNIX环境高级编程》(APUE) 笔记第一章 - UNIX基础知识

    1 - UNIX基础知识 Github 地址 1. 操作系统 可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境.通常将这种软件称为 内核 (kernel) .( Linux 是 GN ...

  2. UNIX环境高级编程--第一章 UNIX基础知识

    第一章 UNIX基础知识 1.2 UNIX体系结构   从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境.我们将这种软件称为内核(kernel),因为 它相对较小,且 ...

  3. apue学习笔记(第一章UNIX基础知识)

    总所周知,UNIX环境高级编程是一本很经典的书,之前我粗略的看了一遍,感觉理解得不够深入. 听说写博客可以提高自己的水平,因此趁着这个机会我想把它重新看一遍,并把每一章的笔记写在博客里面. 我学习的时 ...

  4. APUE(1)----UNIX基础知识

    一.UNIX体系结构 所有操作系统都为他们所运行的程序提供服务,典型的服务包括:执行新程序.打开文件.读文件.分配存储区等.严格意义上来说,操作系统可以定义为一种软件,它控制计算机硬件资源,提供程序运 ...

  5. APUE 学习笔记(一) Unix基础知识

    1. Unix 体系结构   内核的接口被称为系统调用 公用函数库构建在系统调用接口之上 应用软件既可以调用公用函数库,也可以直接进行系统调用   2. 文件和目录 目录操作函数:opendir--- ...

  6. 第一章:UNIX基础知识

    本章内容主要是为了学习UNIX的基本知识和一些最基本的系统函数. 学习的关键就是跟随者书本敲代码.本节遇到的第一个问题就死本书的apue.h这个文件:一开始没有注意这个文件,盲目的去百度,一番百度之后 ...

  7. UNIX基础知识之程序和进程

    一.程序 程序(program)是存放在磁盘上.处于某个目录中的一个可执行文件.使用6个exec函数中的一个由内核将程序读入存储器,并使其执行. 二.进程和进程ID 程序的执行实例被称为进程(proc ...

  8. 《UNIX环境高级编程》笔记——1.UNIX基础知识

    这一章节侧重一些基本概念和书中用到的一些名词. 一.引言 所有的操作都提供服务,典型的服务包括:执行新程序.打开文件.读写文件.分配存储区以及获得当前时间等. 二.UNIX体系结构 其实linux常见 ...

  9. UNIX,基础知识,文件IO,文件和目录

    2015.1.27星期二,早晨阴天,中午下雪了今天上午老师不上课,程序语句,记一下:main(void){ int c; while((c = getc(stdin)) != EOF) if(putc ...

  10. UNIX基础知识之时间值

    本篇博文内容摘自<UNIX环境高级编程>(第二版),仅作个人学习记录所用.关于本书可参考:http://www.apuebook.com/. 长期以来,UNIX系统一直使用两种不同的时间值 ...

随机推荐

  1. Android Paint画笔及Color .

    引自:http://blog.csdn.net/q445697127/article/details/7736926 Paint paint = new Paint(); // 设置paint为无锯齿 ...

  2. 8数码,欺我太甚!<bfs+康拓展开>

    不多述,直接上代码,至于康拓展开,以前的文章里有 #include<iostream> #include<cstdio> #include<queue> using ...

  3. brbustoj 1818 石子合并问题--直线版

    比较经典且基础的区间dp,转移方程为 dp_max[i][j] = max(dp_max[i][j],dp_max[i][k] + dp_max[k+1][j] + sum[j]-sum[i-1]); ...

  4. 关于struts2的web.xml配置

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "- ...

  5. mark一篇文章--用nodejs搭建一个本地反向代理环境

    调试线上代码的时候,我们经常遇到的一个问题就是 本地一套环境,线上一套环境,本地没有的文件用线上的这种需求.我简单来说下使用nodejs如何做到. 先说下不用nodejs我们怎么做,工具比如fiddl ...

  6. Size Balanced Tree(SBT) 模板

    首先是从二叉搜索树开始,一棵二叉搜索树的定义是: 1.这是一棵二叉树: 2.令x为二叉树中某个结点上表示的值,那么其左子树上所有结点的值都要不大于x,其右子树上所有结点的值都要不小于x. 由二叉搜索树 ...

  7. 只有mdf 没有 日志 恢复数据库

    1.先建一个与你要恢复的数据库名称一样的数据库.2.停止sql server,把你的数据库替换这个数据库.3.重启sql server,把数据库设置为紧急状态.  sp_configure 'allo ...

  8. json转义字符串

    json前台写数据 @RequestMapping("/addUserJson") public void addUserJson(User user,HttpServletReq ...

  9. IGeoFeatureLayer

    Members   All Properties Methods Inherited Non-inherited Description AnnotationProperties Annotation ...

  10. Codeforces#373 Div2

    Ranting重新回到浅蓝的一场比赛 Problem A 题意:月亮的大小是按照这样的顺序排列的0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ...