管道,鳩占鵲巢

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;  //壽終正寢
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,933評論 18 139
  • exec(鳩占鵲巢) 查找文件:fins /usr execl 模擬一個終端,可以同時打開兩個文件 模擬一個終端 ...
    帥碧閱讀 347評論 1 2
  • 1:InputChannel提供函數創建底層的Pipe對象 2: 1)客戶端需要新建窗口 2)new ViewRo...
    自由人是工程師閱讀 5,395評論 0 18
  • 本文參加#感悟三下鄉,青春筑夢行#活動,本人承諾,文章內容為原創,且未在其他平臺發表過。 今年的七月很特別,這...
    蘭舟催發ajk閱讀 613評論 3 13
  • 緣分,是一種無法用言語表達的微妙,它該來的時候,便會毫無征兆的降臨 3.14 第一次遇見他,是肥肥帶我去球館打球,...
    錒娥娥娥閱讀 316評論 0 1