zoukankan      html  css  js  c++  java
  • apue- chapter 1 UNIX基础知识

    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函数返回的每一行都以换行符结束,后面紧随一个'',需要将换行符号替换为''
            if(buf[strlen(buf)-1]=='
    ')//最后一个字符是换行符
                buf[strlen(buf)-1]='';//将其替换为结束符号
            //调用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
    ",strerror(EACCES));
        errno=ENOENT;
        //基于当前errno的值,在标准错误上产生一条出错信息
        perror(argv[0]);
    
    }

    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)-1]=='
    ')
                buf[strlen(buf)-1]='';
            if((pid=fork())<0){
                cout<<"fork error"<<endl;
            }else if(pid==0){
                execlp(buf,buf,(char *)0);
                cout<<"could't execute :"<<buf<<endl;
                exit(-1);
            }
            if((pid=waitpid(pid,&status,0))<0)
                cout<<"wait pid error"<<endl;
            cout<<"%% ";
        }
        return 0;
    }

    运行截图:

      

  • 相关阅读:
    总结随笔
    Beta冲刺第七天
    Beta冲刺第六天
    Beta冲刺第五天
    Beta冲刺第四天
    Beta冲刺第三天
    POJ 2240 Arbitrage
    POJ 3660 Cow Contest
    POJ 1797 Heavy Transportation
    LightOJ 1123 Trail Maintenance
  • 原文地址:https://www.cnblogs.com/zhoudayang/p/5300198.html
Copyright © 2011-2022 走看看