一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Linux|Centos|Ubuntu|系統(tǒng)進(jìn)程|Fedora|注冊表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服務(wù)器之家 - 服務(wù)器系統(tǒng) - Linux - linux編程之pipe()函數(shù)詳解

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

2021-11-30 16:09流云攬月 Linux

本篇文章主要介紹了linux編程之pipe()函數(shù)詳解,具有一定的參考價值,有需要的可以了解一下。

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

?
1
2
3
#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。但是可以使用命名管道。

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

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

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

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

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

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

在上例程序中,子進(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)程訪問。       

?
1
2
3
4
5
#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的例子

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*
 * 有親緣關(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 端的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*
 * 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);
}

客戶端的例子: 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
 * 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í)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:http://www.cnblogs.com/kunhu/p/3608109.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日本一区免费观看 | 无码射肉在线播放视频 | 王小军怎么了最新消息 | 国产欧美日韩一区二区三区在线 | 5g影院天天影院天天爽影院网站 | 午夜久| 黑人好大好硬好深好爽想要h | 久久99r66热这里只有精品 | 欧美丰满大乳大屁在线观看股 | 出水小说 | 国产美女久久精品香蕉69 | 亚洲阿v天堂在线2017 | 人人揉人人爽五月天视频 | 垫底辣妹免费观看完整版 | 免费高清视频日本 | 久久精品国产欧美日韩99热 | 日韩免费在线视频 | 欧美日韩高清观看一区二区 | 短篇艳妇系列 | 男人天堂网站在线 | 欧美日韩国产一区二区三区伦 | 欧美一级高清片免费一级 | 国产成人h综合亚洲欧美在线 | 人成午夜免费大片在线观看 | 天天做天天爱天天操 | 手机在线免费观看视频 | 欧美一区二区三区视视频 | 欧美专区在线观看 | 久久99国产视频 | 国产精品调教 | 91精品久久 | 欧美一级高清免费a | 欧美一级片观看 | 四虎库| 四虎国产精品免费入口 | 亚洲国产精品日本无码网站 | 日本一区二区三区四区无限 | 我年轻漂亮的继坶2中字在线播放 | 亚洲国产美女精品久久 | 亚洲无线一二三区2021 | 亚洲精品6久久久久中文字幕 |