1.C++实现ls命令

#include<dirent.h>
#include<stdlib.h>
#include<iostream>
#include "apue.h"
using namespace std;
int main(int argc,char * argv[]){
DIR *d
struct dirent *dirp;
if(argc!=2){
cout<<"usage: ls directory_name"<<endl;
exit(-1);
}
if((dp=opendir(argv[1]))==NULL){
cout<<"can't open "<<argv[1]<<endl;
}
//循环读取目录项
while((dirp=readdir(dp))!=NULL){
//输出文件名称
cout<<dirp->d_name<<endl;
}
closedir(dp); exit(0);
}

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

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

#include "apue.h"
#include<iostream>
using namespace std;
#define BUFFSIZE 4096
int main(){
int n;
//缓冲
char buf[BUFFSIZE];
//从标准输入中读取,缓冲区大小为BUFFSIZE,缓冲区对应buf
while((n=read(STDIN_FILENO,buf,BUFFSIZE))>0){
//向标准输出输出buf中的内容
if(write(STDOUT_FILENO,buf,n)!=n)
cout<<"wirte error"<<endl;
}
//读取标准输入出错
if(n<0)
cout<<"read error"<<endl;
exit(0);
}

运行截图:

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

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

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

#include "apue.h"
#include <iostream>
using namespace std;
int main(){
int c;
while((c=getc(stdin))!=EOF){
if(putc(c,stdout)==EOF)
cout<<"output error"<<endl;
}
if(ferror(stdin))
cout<<"input error"<<endl; return 0;
}

4.输出进程ID

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

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

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

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

hello world from process ID18357

hello world from process ID18385

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

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

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

执行过程:

%% ls
b CMakeFiles hello_world Makefile
CMakeCache.txt cmake_install.cmake hello_world.cbp
%% date
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标准定义了两个函数,用于打印出错的信息。

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

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

#include<iostream>

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

7.用户id和组id

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

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

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

8. 信号

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

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

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

#include<iostream>
#include "apue.h"
#include <sys/wait.h>
using namespace std;
//用于捕捉信号的函数
static void sig_int(int signo){//信号处理函数,输出Interrupt
cout<<"Interrupt "<<endl;
}
int main(){
char buf[MAXLINE];
pid_t pid;
int status;
if(signal(SIGINT,sig_int)==SIG_ERR)//绑定信号
cout<<"signal error"<<endl;
cout<<"%% ";
while(fgets(buf,MAXLINE,stdin)!=NULL){
if(buf[strlen(buf)-]=='\n')
buf[strlen(buf)-]='\0';
if((pid=fork())<){
cout<<"fork error"<<endl;
}else if(pid==){
execlp(buf,buf,(char *));
cout<<"could't execute :"<<buf<<endl;
exit(-);
}
if((pid=waitpid(pid,&status,))<)
cout<<"wait pid error"<<endl;
cout<<"%% ";
}
return ;
}

运行截图:

  

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. int *p[4]与int (*q)[4]的区别

    以上定义涉及两个运算符:“*”(间接引用).“[]”(下标),“[]”的优先级别大于“*”的优先级别. 首先看int *p[4],“[]”的优先级别高,所以它首先是个大小为4的数组,即p[4]:剩下的 ...

  2. jq中的ajax

    jq对ajax进行了封装,在jq中$.ajax()方法是最底层的方法,第二层是load() , get() , post()方法,第三层是$.getScript()和$.getJSON().基本第二种 ...

  3. jq模拟操作

    1.常用模拟 trigger() $('#btn').trigger('click'); 当页面加载完,点击事件就会完成 上面也可以简写成:$('#btn').click(); 2.触发自定义事件 t ...

  4. BCDedit 研究

    bcdedit的研究 系统引导安装 2009-11-12 22:21:13 阅读13 评论0 字号:大中小 首先说明下引导: 微软在Vista之前的系统,采用的是Ntldr来进行引导系统,使用的是bo ...

  5. FusionCharts使用问题及解决方法(五)-FusionCharts常见问题大全

    在前4篇文章中,我们总结了FusionCharts XT图表使用中的一些常见问题(FAQ)及解决方法,本文继续讨论FusionCharts使用者常见的一些复杂报错及错误的调试/解决方法. 问题描述:是 ...

  6. OpenGL学习-------点、直线、多边形

    上一课中,我们学习了如何绘制几何图形,但大家如果多写几个程序,就会发现其实还是有些郁闷之处.例如:点太小,难以看清楚:直线也太细,不舒服:或者想画虚线,但不知道方法只能用许多短直线,甚至用点组合而成. ...

  7. AES加密,解决了同步问题,和随机密钥和固定密钥,多端通信加密不一致解决办法

    1.密钥随机生成. import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyEx ...

  8. bootstrap-table 表头和内容对不齐解决办法

    偶然机会学习bootstrap,表格利用bootstrap-table实现,使用bootstrap-table过程中,发现了一个非常棘手的问题,在ie浏览器中,表格的表头和内容对不齐,特别是列比较多且 ...

  9. 基于Spring的异步系统实现方案

    一般的实现方案 发送异步消息所使用的工具类: import java.util.Date; import javax.jms.Destination; import javax.jms.JMSExce ...

  10. flex4 list 自动适应高度

    <s:List width="100%"> <s:layout> <s:VerticalLayout useVirtualLayout="f ...