最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

linux編程之pipe()函數(shù)詳解

 更新時間:2016年11月23日 08:43:19   作者:流云攬月  
本篇文章主要介紹了linux編程之pipe()函數(shù)詳解,具有一定的參考價值,有需要的可以了解一下。

管道是一種把兩個進(jìn)程之間的標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出連接起來的機(jī)制,從而提供一種讓多個進(jìn)程間通信的方法,當(dāng)進(jìn)程創(chuàng)建管道時,每次都需要提供兩個文件描述符來操作管道。其中一個對管道進(jìn)行寫操作,另一個對管道進(jìn)行讀操作。對管道的讀寫與一般的IO系統(tǒng)函數(shù)一致,使用write()函數(shù)寫入數(shù)據(jù),使用read()讀出數(shù)據(jù)。

#include<unistd.h>

int pipe(int filedes[2]);

返回值:成功,返回0,否則返回-1。參數(shù)數(shù)組包含pipe使用的兩個文件的描述符。fd[0]:讀管道,fd[1]:寫管道。

必須在fork()中調(diào)用pipe(),否則子進(jìn)程不會繼承文件描述符。兩個進(jìn)程不共享祖先進(jìn)程,就不能使用pipe。但是可以使用命名管道。


當(dāng)管道進(jìn)行寫入操作的時候,如果寫入的數(shù)據(jù)小于128K則是非原子的,如果大于128K字節(jié),緩沖區(qū)的數(shù)據(jù)將被連續(xù)地寫入管道,直到全部數(shù)據(jù)寫完為止,如果沒有進(jìn)程讀取數(shù)據(jù),則將一直阻塞,如下:

在上例程序中,子進(jìn)程一次性寫入128K數(shù)據(jù),當(dāng)父進(jìn)程將全部數(shù)據(jù)讀取完畢的時候,子進(jìn)程的write()函數(shù)才結(jié)束阻塞并且

返回寫入信息。

命名管道FIFO

管道最大的劣勢就是沒有名字,只能用于有一個共同祖先進(jìn)程的各個進(jìn)程之間。FIFO代表先進(jìn)先出,單它是一個單向數(shù)據(jù)流,也就是半雙工,和

管道不同的是:每個FIFO都有一個路徑與之關(guān)聯(lián),從而允許無親緣關(guān)系的進(jìn)程訪問。       

#include <sys/types.h>

    #include <sys/stat.h>

   int mkfifo(const char *pathname, mode_t mode);

這里pathname是路徑名,mode是sys/stat.h里面定義的創(chuàng)建文件的權(quán)限.

有親緣關(guān)系進(jìn)程間的fifo的例子

/*
 * 有親緣關(guān)系的進(jìn)程間的fifo的使用
 * fifo 使用的簡單例子
 */

#include "../all.h"

#define FIFO_PATH "/tmp/hover_fifo"


void 
do_sig(int signo)
{
  if (signo == SIGCHLD)
    while (waitpid(-1, NULL, WNOHANG) > 0)
      ;
}


int
main(void)
{
  int ret;
  int fdr, fdw;
  pid_t pid;

  char words[10] = "123456789";
  char buf[10] = {'\0'};  
  
  // 創(chuàng)建它,若存在則不算是錯誤,
  // 若想修改其屬性需要先打開得到fd,然后用fcntl來獲取屬性,然后設(shè)置屬性.

  if (((ret = mkfifo(FIFO_PATH, FILE_MODE)) == -1) 

           && (errno != EEXIST))
    perr_exit("mkfifo()");
  fprintf(stderr, "fifo : %s created successfully!\n", FIFO_PATH);

  signal(SIGCHLD, do_sig);

  pid = fork();
  if (pid == 0) { // child

    if ((fdr = open(FIFO_PATH, O_WRONLY)) < 0) // 打開fifo用來寫
      perr_exit("open()");
    sleep(2);

    // 寫入數(shù)據(jù)
    if (write(fdr, words, sizeof(words)) != sizeof(words)) 
      perr_exit("write");
    fprintf(stderr, "child write : %s\n", words);
    close(fdw);
  } else if (pid > 0) { // parent

    if ((fdr = open(FIFO_PATH, O_RDONLY)) < 0) // 打開fifo用來讀

      perr_exit("open()");

    fprintf(stderr, "I father read, waiting for child ...\n");
    if (read(fdr, buf, 9) != 9) //讀數(shù)據(jù)
      perr_exit("read");

    fprintf(stderr, "father get buf : %s\n", buf);
    close(fdr);
  }
  // 到這里fifo管道并沒有被刪除,必須手動調(diào)用函數(shù)unlink或remove刪除.

  return 0;  
}

 從例子上可以看出使用fifo時需要注意:

*fifo管道是先調(diào)用mkfifo創(chuàng)建,然后再用open打開得到fd來使用.

*在打開fifo時要注意,它是半雙工的的,一般不能使用O_RDWR打開,而只能用只讀或只寫打開.

fifo可以用在非親緣關(guān)系的進(jìn)程間,而它的真正用途是在服務(wù)器和客戶端之間. 由于它是半雙工的所以,如果要進(jìn)行客戶端和服務(wù)器雙方的通信的話,

每個方向都必須建立兩個管道,一個用于讀,一個用于寫.

下面是一個服務(wù)器,對多個客戶端的fifo的例子:

server 端的例子:

/*
 * FIFO server
 */

#include "all.h"

int
main(void)
{
  int fdw, fdw2;
  int fdr;
  char clt_path[PATH_LEN] = {'\0'};
  char buf[MAX_LINE] = {'\0'};
  char *p;
  int n;
  
  if (mkfifo(FIFO_SVR, FILE_MODE) == -1 && errno != EEXIST)  
    perr_exit("mkfifo()");  
  if ((fdr = open(FIFO_SVR, O_RDONLY)) < 0)  
    perr_exit("open()");
  /* 
   * 根據(jù)fifo的創(chuàng)建規(guī)則, 若從一個空管道或fifo讀, 

   * 而在讀之前管道或fifo有打開來寫的操作, 那么讀操作將會阻塞 
   * 直到管道或fifo不打開來讀, 或管道或fifo中有數(shù)據(jù)為止. 

   *

   * 這里,我們的fifo本來是打開用來讀的,但是為了,read不返回0,

   * 讓每次client端讀完都阻塞在fifo上,我們又打開一次來讀.
   * 見unpv2 charper 4.7
   */
  if ((fdw2 = open(FIFO_SVR, O_WRONLY)) < 0)  
    fprintf(stderr, "open()");
  
  while (1) {
    /* read client fifo path from FIFO_SVR */

   /* 這里由于FIFO_SVR有打開來寫的操作,所以當(dāng)管道沒有數(shù)據(jù)時, 

   * read會阻塞,而不是返回0. 

   */
    if (read(fdr, clt_path, PATH_LEN) < 0) {
      fprintf(stderr, "read fifo client path error : %s\n", strerror(errno));  
      break;
    }
    if ((p = strstr(clt_path, "\r\n")) == NULL) {
      fprintf(stderr, "clt_path error: %s\n", clt_path);
      break;
    }
    *p = '\0';
    DBG("clt_path", clt_path);
    if (access(clt_path, W_OK) == -1) { // client fifo ok, but no permission

      perror("access()");  
      continue;
    }
    /* open client fifo for write */
    if ((fdw = open(clt_path, O_WRONLY)) < 0) {
      perror("open()");  
      continue;
    }
    if ((n = read(fdr, buf, WORDS_LEN)) > 0) { /* read server words is ok */
      printf("server read words : %s\n", buf);
      buf[n] = '\0';
      write(fdw, buf, strlen(buf));  
    }
  }
  
  close(fdw);  
  unlink(FIFO_SVR);
  exit(0);
}

客戶端的例子: 

/*
 * Fifo client
 *
 */
#include "all.h"

int
main(void)
{
  int fdr, fdw;
  pid_t pid;  
  char clt_path[PATH_LEN] = {'\0'};
  char buf[MAX_LINE] = {'\0'};
  char buf_path[MAX_LINE] = {'\0'};
  
  snprintf(clt_path, PATH_LEN, FIFO_CLT_FMT, (long)getpid());    
  DBG("clt_path1 = ", clt_path);
  snprintf(buf_path, PATH_LEN, "%s\r\n", clt_path);

  if (mkfifo(clt_path, FILE_MODE) == -1 && errno != EEXIST)  
    perr_exit("mkfifo()");

  /* client open clt_path for read
   * open server for write 
    */
  if ((fdw = open(FIFO_SVR, O_WRONLY)) < 0) 
    perr_exit("open()");
  
  /* write my fifo path to server */  
  if (write(fdw, buf_path, PATH_LEN) != PATH_LEN)    
    perr_exit("write()");
  if (write(fdw, WORDS, WORDS_LEN) < 0)  /* write words to fifo server */
    perr_exit("error");

  if ((fdr = open(clt_path, O_RDONLY)) < 0)  
    perr_exit("open()");
  if (read(fdr, buf, WORDS_LEN) > 0) {   /* read reply from fifo server */
    buf[WORDS_LEN] = '\0';
    printf("server said : %s\n", buf);
  }
  
  close(fdr);
  unlink(clt_path);
  
  exit(0);
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • ubuntn備份方法總結(jié)(四種)

    ubuntn備份方法總結(jié)(四種)

    本文給大家收藏整理了四種關(guān)于ubuntn備份方法,每種方法給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友參考下吧
    2018-11-11
  • Linux系統(tǒng)中KafKa安裝和使用方法 java客戶端連接kafka過程

    Linux系統(tǒng)中KafKa安裝和使用方法 java客戶端連接kafka過程

    這篇文章主要介紹了Linux系統(tǒng)中KafKa安裝和使用方法 java客戶端連接kafka過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 使用VMware虛擬機(jī)安裝Linux(CentOS7鏡像)

    使用VMware虛擬機(jī)安裝Linux(CentOS7鏡像)

    這篇文章介紹了使用VMware虛擬機(jī)安裝Linux(CentOS7鏡像)的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • CentOS7安裝PHP7 Redis擴(kuò)展的方法步驟

    CentOS7安裝PHP7 Redis擴(kuò)展的方法步驟

    這篇文章主要介紹了CentOS7安裝PHP7 Redis擴(kuò)展的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-04-04
  • Windows10安裝linux子系統(tǒng)的兩種方式(圖文詳解)

    Windows10安裝linux子系統(tǒng)的兩種方式(圖文詳解)

    這篇文章主要介紹了Windows10安裝linux子系統(tǒng)的兩種方式,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Linux新建虛擬機(jī)Ubuntu的圖文教程

    Linux新建虛擬機(jī)Ubuntu的圖文教程

    這篇文章主要詳細(xì)介紹了Linux新建虛擬機(jī)Ubuntu的教程,文章通過圖文結(jié)合的方式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-09-09
  • Linux如何定時執(zhí)行任務(wù)教程

    Linux如何定時執(zhí)行任務(wù)教程

    Linux crontab是采用定期執(zhí)行程序的命令,當(dāng)安裝完成操作 系統(tǒng)后,默認(rèn)便會啟動此任務(wù)調(diào)度命令,crond命令每分鐘都會定期檢查是否要執(zhí)行任務(wù)的工作,如果要執(zhí)行的工作便會自動執(zhí)行該任務(wù)。本文主要介紹了定時任務(wù)Crontab的使用,需要的可以學(xué)習(xí)一下
    2023-04-04
  • bt寶塔面板php7.3、php7.4不支持ZipArchive解決方法

    bt寶塔面板php7.3、php7.4不支持ZipArchive解決方法

    這篇文章主要介紹了bt寶塔面板php7.3、php7.4不支持ZipArchive解決方法,需要的朋友可以參考下
    2020-06-06
  • Centos 7.4服務(wù)器時間同步配置方法【基于NTP服務(wù)】

    Centos 7.4服務(wù)器時間同步配置方法【基于NTP服務(wù)】

    這篇文章主要介紹了Centos 7.4服務(wù)器時間同步配置方法,結(jié)合實(shí)例形式分析了NTP服務(wù)器安裝、啟動、設(shè)置時間同步等相關(guān)命令及問題解決方法,需要的朋友可以參考下
    2019-03-03
  • Linux的Socket IO模型趣解

    Linux的Socket IO模型趣解

    這篇文章主要通過一個幽默的方式為大家詳細(xì)介紹了Linux的Socket IO模型,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11

最新評論

宁夏| 凤冈县| 伽师县| 弋阳县| 邓州市| 开平市| 南郑县| 松阳县| 内黄县| 津市市| 微博| 海伦市| 云南省| 榆社县| 德化县| 大同市| 博白县| 武强县| 牟定县| 沾化县| 大城县| 会东县| 巢湖市| 文山县| 涟源市| 固安县| 弋阳县| 溆浦县| 桃园县| 望城县| 琼结县| 烟台市| 罗源县| 陆川县| 米泉市| 洮南市| 武城县| 新密市| 保德县| 巩义市| 延吉市|