欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2016年11月23日 08:43:19   作者:流云攬?jiān)? 
本篇文章主要介紹了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)文章

  • Ubuntu環(huán)境下使用G++編譯CPP文件

    Ubuntu環(huán)境下使用G++編譯CPP文件

    今天小編就為大家分享一篇關(guān)于Ubuntu環(huán)境下使用G++編譯CPP文件,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • Apache mod_rewrite中的REQUEST_URI使用實(shí)例

    Apache mod_rewrite中的REQUEST_URI使用實(shí)例

    這篇文章主要介紹了Apache mod_rewrite中的REQUEST_URI使用實(shí)例,本文使用一個實(shí)例講解如何使用REQUEST_URI,需要的朋友可以參考下
    2015-01-01
  • Linux cp命令參數(shù)簡介

    Linux cp命令參數(shù)簡介

    這篇文章主要介紹了Linux cp命令參數(shù)簡介,需要的朋友可以參考下
    2014-07-07
  • ubuntu14.04安裝jdk1.8的教程

    ubuntu14.04安裝jdk1.8的教程

    這篇文章主要介紹了ubuntu14.04安裝jdk1.8的教程,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • Linux下的chkconfig命令詳解

    Linux下的chkconfig命令詳解

    大家都知道chkconfig命令在linux中使用是非常的關(guān)鍵的,我們可以利用chkconfig來對系統(tǒng)的一些啟動與禁止相關(guān)設(shè)置,下面這篇文章小編就來給大家詳細(xì)的介紹Linux下的chkconfig命令用法,有需要的朋友們可以參考學(xué)習(xí),下面來一起看看吧。
    2016-11-11
  • 利用lynis如何進(jìn)行l(wèi)inux漏洞掃描詳解

    利用lynis如何進(jìn)行l(wèi)inux漏洞掃描詳解

    這篇文章主要給大家介紹了關(guān)于利用lynis如何進(jìn)行l(wèi)inux漏洞掃描的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-06-06
  • Linux 遠(yuǎn)程管理及sshd服務(wù)驗(yàn)證知識點(diǎn)詳解

    Linux 遠(yuǎn)程管理及sshd服務(wù)驗(yàn)證知識點(diǎn)詳解

    在本篇文章里小編給大家整理了一篇關(guān)于Linux 遠(yuǎn)程管理及sshd服務(wù)驗(yàn)證知識點(diǎn)總結(jié),有需要的朋友們跟著學(xué)習(xí)參考下。
    2021-12-12
  • ubuntu16.04自動設(shè)置行號的步驟詳解

    ubuntu16.04自動設(shè)置行號的步驟詳解

    這篇文章主要介紹了ubuntu16.04自動設(shè)置行號的步驟,文中給大家提到了Ubuntu vi設(shè)置行號的方法,感興趣的朋友跟隨腳本之家小編一起看看吧
    2018-08-08
  • Linux Apache設(shè)置壓縮及緩存

    Linux Apache設(shè)置壓縮及緩存

    本篇文章給大家詳細(xì)解說了Linux中Apache設(shè)置壓縮及緩存的方法,需要的朋友跟著學(xué)習(xí)下。
    2018-02-02
  • crontab執(zhí)行結(jié)果未通過發(fā)送mail通知用戶的方法

    crontab執(zhí)行結(jié)果未通過發(fā)送mail通知用戶的方法

    這篇文章主要給大家介紹了關(guān)于crontab執(zhí)行結(jié)果未通過發(fā)送mail通知用戶的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用linux系統(tǒng)具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06

最新評論