管道,鸠占鹊巢

2017-02-15  本文已影响0人  萌面大叔2

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;  //寿终正寝
}
上一篇下一篇

猜你喜欢

热点阅读