美文网首页
管道,鸠占鹊巢

管道,鸠占鹊巢

作者: 萌面大叔2 | 来源:发表于2017-02-15 13:06 被阅读0次

    env | grep 2016查路径

    捕获.PNG

    写代码完成目录拷贝(注:包含子目录)

    #include <stdio.h>
    #include <string.h>  
    #include <errno.h>  //errno
    /*open   stat*/
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h> //read()   write()
    /*dir ope*/
    #include <sys/types.h>
    #include <dirent.h>
    #include <stdlib.h> //exit()
    
    #define PER_IO_BYTES 4096
    
    int fileType(mode_t mode)
    {
        int ret = -1;
        switch (mode & S_IFMT)
        {
        case S_IFREG:
            ret = 0;
            break;
        case S_IFDIR:
            ret = 1;
            break;
        default:
            ret = -1;
            break;
        }
        return ret;
    }
    
    void copyRegFile(const char *pDestPathname
                     , const char *pSrcPathname)
    {
        //对形参进行有效性检查
        if (NULL == pDestPathname || NULL == pSrcPathname)
        {
            return;
        }
    
        int iDestFd = -1;
        //以写的方式打开目标文件,如果不存在则创建
        iDestFd = open(pDestPathname, O_WRONLY | O_CREAT
                       , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (-1 == iDestFd)
        {
            perror("open dest");
            exit(EXIT_FAILURE);
        }
        int iSrcFd = -1;
        //以读的方式打开源文件,如果不存在则创建
        iSrcFd = open(pSrcPathname, O_RDONLY | O_CREAT
                       , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (-1 == iSrcFd)
        {
            perror("open src");
            exit(EXIT_FAILURE);
        }
    
        unsigned char caBuf[PER_IO_BYTES] = {'\0'};
        int ret = -1;
        //从源文件循环读取数据
        while ((ret = read(iSrcFd, caBuf, PER_IO_BYTES)))
        {
            //判断数据读取成功失败与否
            if (-1 == ret)
            {
                //如果发生的错误是EAGAIN,EINTR
                //需要重新读取数据
                if (EAGAIN == errno || EINTR == errno)
                {
                    continue;
                }
                //如果是其他错误,则显示错误信息并且退出程序
                perror("read src");
                //close(iSrcFd);
                //close(iDestFd);
                exit(EXIT_FAILURE);
            }
            //如果返回值为0,表示已读到文件末尾,没有数据可读
            //则文件拷贝结束
            else if (0 == ret)
            {
                break;
            }
            while (1)
            {
                //将读取到的数据写入到目标文件
                ret = write(iDestFd, caBuf, ret);
                if (-1 == ret)
                {
                    if (EAGAIN == errno || EINTR == errno)
                    {
                        continue;   
                    }
                    perror("write dest");
                    //close(iSrcFd);
                    //close(iDestFd);
                    exit(EXIT_FAILURE);
                }
                break;
            }
        }
        close(iSrcFd);
        close(iDestFd);
    }
    
    void copyDirFile(const char *pDestDirName
                     , const char *pSrcDirName)
    {
        if (NULL == pDestDirName || NULL == pSrcDirName)
        {
            return;
        }
        int ret = -1;
        //创建目录
        ret = mkdir(pDestDirName, 0775);
        if (-1 == ret)
        {
            if (EEXIST != errno)
            {
                perror("mkdir");
                exit(EXIT_FAILURE);
            }
        }
        DIR *pDestDir = NULL;
        //打开目标目录
        pDestDir = opendir(pDestDirName);
        if (NULL == pDestDir)
        {
            perror("open dest dir");
            exit(EXIT_FAILURE);
        }
        DIR *pSrcDir = NULL;
        //打开源目录
        pSrcDir = opendir(pSrcDirName);
        if (NULL == pSrcDir)
        {
            perror("open src dir");
            exit(EXIT_FAILURE);
        }
        char caDestFileName[64] = {'\0'};
        char caSrcFileName[64] = {'\0'};
        struct stat fileStat;
        struct dirent *pDirent = NULL;
        pDirent = readdir(pSrcDir);
        int iLen = 0;
        while (NULL != pDirent)
        {
            if (0 != strcmp(pDirent->d_name, "..")
                && 0 != strcmp(pDirent->d_name, "."))
            {
                //拼接路径名
                strcpy(caSrcFileName, pSrcDirName);
                iLen = strlen(pSrcDirName);
                if (pSrcDirName[iLen-1] != '/')
                {
                    strcat(caSrcFileName, "/");
                }
                strcat(caSrcFileName, pDirent->d_name);
                printf("%s\n", caSrcFileName);
    /********************************************************/
                strcpy(caDestFileName, pDestDirName);
                iLen = strlen(pDestDirName);
                if (pDestDirName[iLen-1] != '/')
                {
                    strcat(caDestFileName, "/");
                }
                strcat(caDestFileName, pDirent->d_name);
    /********************************************************/
                //获得文件status
                ret = stat(caSrcFileName, &fileStat);
                if (-1 == ret)
                {
                    perror("stat");
                    exit(EXIT_FAILURE);
                }
                //判断文件的类型
                ret = fileType(fileStat.st_mode);
                switch (ret)
                {
                case 0:
                    copyRegFile(caDestFileName, caSrcFileName);
                    break;
                case 1:
                    copyDirFile(caDestFileName, caSrcFileName);
                    break;
                default:
                    break;
                }
            }
    /********************************************************/
            pDirent = readdir(pSrcDir);
        }
    }
    
    int main(int argc, char *argv[])
    {
        //copyRegFile(argv[2], argv[1]);
        copyDirFile(argv[2], argv[1]);
    
        return 0;
    }
    

    鸠占鹊巢(execl,ececlp,execv,execvp)

    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        int ret = -1;
        //使用新进程镜像替换当前进程镜像
        //但是当前进程的ID被新进程使用
        //-->鸠占鹊巢,巢还在,鹊变成了鸠
        //第一个参数:可执行文件的路径
        //之后的参数:可执行文件执行的方式
        //ret = execl("/bin/ls", "ls", "/usr/include", "-l", NULL);
        //ret = execl("./test", "test", NULL);
        //ret = execl("/usr/bin/gedit", "gedit", NULL);
        //ret = execl("/usr/bin/gedit", "gedit", "dirCopy.c", NULL);
        //可以不指定需要执行文件的路径
        //启动该执行文件时,到系统默认路径下去找该执行文件
        //若找到了则执行,否则出错返回
        //ret = execlp("gedit", "gedit", "dirCopy.c", NULL);
    #if 0
        ret = execlp("myTest", "myTest", NULL);
        printf("ret = %d\n", ret);
        if (-1 == ret)
        {
            perror("execlp");
            return -1;
        }
    #endif
    
        //char *const argv[] = {"ls", "/usr/include", "-l", NULL};
        //ret = execv("/bin/ls", argv);
        char *const argv[] = {"gedit", "dirCopy.c", NULL};
        ret = execvp("gedit", argv);
    
        return 0;
    }
    

    eg:execv

    #include <stdio.h>
    #include <string.h>
    /*fork  exec*/
    #include <unistd.h>
    
    int main(int argc, char *argv[])
    {
        pid_t pid = -1;
        pid = fork();
        if (pid > 0)  //parent
        {
            while (1) 
            {
                printf("this is parent\n");
                sleep(1);           
            }
        }
        else if (0 == pid)
        {
            //./fe /bin/ls  /usr/include -l
            int ret = -1;
            ret = execv(argv[1], argv+1);
            if (-1 == ret)
            {
                perror("execv");
                return -1;
            }
        }
    
        return 0;
    }
    

    运行结果:


    捕获.PNG2.PNG

    管道pipe

    #include <unistd.h>  //pipe()  fork()
    #include <stdio.h>
    #include <string.h>
    
    //通过pipe()函数创建的管道属于无名管道
    //只能在父子进程间或者子进程间使用
    //创建该管道的进程一旦结束,则该无名管道将会被销毁
    int main(void)
    {
        int pipefd[2] = {-1};
        int ret = -1;
        //创建管道,管道两端描述符存储到pipefd数组中
        //pipefd[0]表示数据流出端,可以从此端读取数据
        //pipefd[1]表示数据进入端,可以往此端写入数据
        ret = pipe(pipefd);
        if (-1 == ret)
        {
            perror("pipe");
            return -1;
        }
    
        pid_t pid = -1;
        //管道的创建的创建是在内核中,不独立属于进程
        //所以,fork产生子进程是并不会再次创建一个管道
        //只是对管道文件描述符进行了一次拷贝
        pid = fork();
        if (pid > 0)  //parent
        {
            close(pipefd[0]);
            while (1)
            {
                write(pipefd[1], "Hello child", 11);
                sleep(1);
            }
        }
        else if (0 == pid)  //child
        {
            close(pipefd[1]);
            char caBuf[32] = {'\0'};
            while (1)
            {
                memset(caBuf, '\0', sizeof(caBuf));
                read(pipefd[0], caBuf, 11);
                printf("%s\n", caBuf);
                sleep(1);
            }
        }
        else if (-1 == pid)  //fork failed
        {
            perror("fork");
            return -1;
        }   
    
        return 0;
    }
    

    eg:pipe-talk

    #include <unistd.h>  //pipe()  fork()
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        int pipefd[2] = {-1};
        int ret = -1;
        ret = pipe(pipefd);
        if (-1 == ret)
        {
            perror("pipe");
            return -1;
        }
    
        pid_t pid = -1;
        pid = fork();
        if (pid > 0)  //parent
        {
            int iSign = 0;
            char caBuf[64] = {'\0'};
            while (1)
            {
                memset(caBuf, '\0', sizeof(caBuf));
                if (0 == iSign)
                {
                    printf("parent-input data:");
                    scanf("%s", caBuf);
                    write(pipefd[1], caBuf, strlen(caBuf));
                    iSign = 1;
                }
                else if (1 == iSign)
                {
                    read(pipefd[0], caBuf, sizeof(caBuf));
                    printf("child says:%s\n", caBuf);
                    iSign = 0;
                }
                sleep(1);
            }
        }
        else if (0 == pid)  //child
        {
            int iSign = 0;
            char caBuf[64] = {'\0'};
            while (1)
            {
                memset(caBuf, '\0', sizeof(caBuf));
                if (0 == iSign)
                {
                    read(pipefd[0], caBuf, sizeof(caBuf));
                    printf("parent says:%s\n", caBuf);
                    iSign = 1;
                }
                else if (1 == iSign)
                {
                    printf("child-input data:");
                    scanf("%s", caBuf);
                    write(pipefd[1], caBuf, strlen(caBuf));
                    iSign = 0;
                }
                sleep(1);
            }
        }
        else if (-1 == pid)  //fork failed
        {
            perror("fork");
            return -1;
        }   
    
        return 0;
    }
    

    运行结果:

    3.PNG

    模仿终端

    #include <stdio.h>
    #include <string.h>
    /*fork  exec*/
    #include <unistd.h>
    #include <stdlib.h>  //malloc
    
    char *getInput(char *argv[])
    {
        int ret = -1;
        int i = 0;
        char *pData = NULL;
        pData = (char *)malloc(64);
        while (EOF != scanf("%s", pData))
        {
            printf("%s\n", pData);
            argv[i] = pData;
            i++;
            pData = (char *)malloc(64);
        }
        free(pData);
        argv[i] = NULL;
        return NULL;
    }
    
    void showArgv(char *argv[])
    {
        int i = 0;
        while (NULL != argv[i])
        {
            printf("%s\n", argv[i]);
            i++;
        }
    }
    
    int main(void)
    {
        char *argv[32] = {NULL};
        while (1)
        {
            printf("MyTermal@sq$");
            getInput(argv);
    
            pid_t pid = -1;
            pid = fork();
            if (0 == pid)
            {
                int ret = -1;
                ret = execvp(argv[0], argv);
                if (-1 == ret)
                {
                    perror("execv");
                    return -1;
                }
            }
        }
    
        return 0;
    }
    

    运行结果:

    捕获.PNG

    atexit

    #include <stdio.h>
    #include <stdlib.h>  //atexit()
    #include <unistd.h>  //_exit()
    
    void fun1()
    {
        printf("fun1...\n");
    }
    void fun2()
    {
        printf("fun2...\n");
    }
    void fun3()
    {
        printf("fun3...\n");
    }
    //进程正常结束时首先在用户态做一些善后工作
    //然后进入内核层做一些善后工作
    
    //return 0  exit()  会首先在用户态做一些善后工作,
    //                  然后进入内核层做一些善后工作
    
    //_exit() 直接进入内核层做一些善后工作
    int main(void)
    {
        //atexit注册的函数会在进程正常结束后被执行
        //执行的顺序和注册顺序相反
        atexit(fun1);
        atexit(fun2);
        atexit(fun3);
    
        _exit(-1);
        //abort(); //已放弃 (核心已转储): 非正常结束
        //exit(-1); //自杀
    
        printf("Hello World\n");
        return 0;  //寿终正寝
    }
    

    相关文章

      网友评论

          本文标题:管道,鸠占鹊巢

          本文链接:https://www.haomeiwen.com/subject/nnqfmttx.html