日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Linux學(xué)習(xí)筆記25——命名管道(FIFO)

系統(tǒng) 2157 0

1 命名管道(FIFO)

????? 管道應(yīng)用的一個重大缺陷就是沒有名字,因此只能用于親緣進(jìn)程之間的通信。 后來從管道為基礎(chǔ)提出命名管道(named pipe,F(xiàn)IFO)的概念,該限制得到了克服。 FIFO不同于管道之處在于它提供一個路徑名與之關(guān)聯(lián),以FIFO的文件形式存在于文件系統(tǒng)中。這樣,即使與FIFO的創(chuàng)建進(jìn)程不存在親緣關(guān)系的進(jìn)程,只要可以訪問該路徑,就能夠彼此通過FIFO相互通信(能夠訪問該路徑的進(jìn)程以及FIFO的創(chuàng)建進(jìn)程之間),因此,通過FIFO不相關(guān)的進(jìn)程也能交換數(shù)據(jù)。 值得注意的是,F(xiàn)IFO嚴(yán)格遵循先進(jìn)先出(first in first out),對管道及FIFO的讀總是從開始處返回數(shù)據(jù),對它們的寫則把數(shù)據(jù)添加到末尾。它們不支持諸如lseek()等文件定位操作。

2 命名管道的創(chuàng)建

        #include <sys/types.h>
        
#include <sys/stat.h>
int mkfifo( const char *pathname,     // 文件的路徑
       mode_t mode           //和open函數(shù)mode一樣
      );

如果pathname路徑下的文件已經(jīng)存在,則mkfifo返回-1,errono將會返回EEXIST。

?

3 命名管道操作

?????? FIFO在文件系統(tǒng)中表現(xiàn)為一個文件,大部分的系統(tǒng)文件調(diào)用都可以在FIFO上面,比如:read,open,write,close,unlink,stat等函數(shù),但是seek函數(shù)不能對FIFO調(diào)用。

? ? ? 可以調(diào)用open打開FIFO,請注意以下方面:?

?????????? A 當(dāng)以阻塞(未指定O_NONBLOCK)方式只讀打開FIFO的時候,則將會被阻塞,直到有其他進(jìn)程以寫方式打開該FIFO。
??? ? ? ?? B 類似的,當(dāng)以阻塞(未指定O_NONBLOCK)方式只寫打開FIFO的時候,則將會被阻塞,直到有其他進(jìn)程以讀方式打開該FIFO
?????????? C 當(dāng)以非阻塞方式(指定O_NONBLOCK)方式只讀打開FIFO的時候,則立即返回。當(dāng)只寫open時,如果沒有進(jìn)程為讀打開FIFO,則返回-1,其errno是ENXIO
如果 寫入管道的數(shù)據(jù)量小于等于PIPE_BUF,則系統(tǒng)保證write為原子操作,多個進(jìn)程同時寫管道,將不會出現(xiàn)穿插;如果寫入數(shù)據(jù)量大于PIPE_BUF,則系統(tǒng)將不保證write為原子操作,多個進(jìn)程同時寫管道,則將有可能會穿插寫入。 這個規(guī)則在命名管道中繼續(xù)適用。
?

4 應(yīng)用實例

???? 本例為一個client-server模式,服務(wù)器端將會創(chuàng)建一個聞名fifo文件(本例中為“/tmp/server”),并讀取該fifo文件。客戶端則打開該fifo文件,并把其請求寫入該FIFO文件。服務(wù)器端讀取該命令并執(zhí)行之。

???? 服務(wù)器端的代碼為:

        #include <unistd.h>
        
          

#include 
        
        <stdlib.h>
        
          

#include 
        
        <stdio.h>
        
          

#include 
        
        <
        
          string
        
        .h>
        
          

#include 
        
        <unistd.h>
        
          

#include 
        
        <fcntl.h>
        
          

#include 
        
        <limits.h>
        
          

#include 
        
        <sys/types.h>
        
          

#include 
        
        <sys/stat.h>
        
          

#include 
        
        <ctype.h>




        
          #define
        
         SERVER_FIFO_NAME "/tmp/serv_fifo"


        
          #define
        
         CLIENT_FIFO_NAME "/tmp/cli_%d_fifo"


        
          #define
        
         BUFFER_SIZE 20




        
          struct
        
        
           data_to_pass_st{

    pid_t client_pid;

    
        
        
          char
        
         some_data[BUFFER_SIZE-
        
          1
        
        
          ];

};




        
        
          int
        
        
           main(){

    
        
        
          int
        
        
           server_fifo_fd,client_fifo_fd;

    
        
        
          struct
        
        
           data_to_pass_st mydata;

    
        
        
          int
        
        
           read_res;

    
        
        
          char
        
         client_fifo[
        
          256
        
        
          ];

    
        
        
          char
        
         *
        
          tmp_char_ptr;

    

    mkfifo(SERVER_FIFO_NAME,
        
        
          0777
        
        
          );

    server_fifo_fd
        
        =
        
          open(SERVER_FIFO_NAME,O_RDONLY);

    
        
        
          if
        
        (server_fifo_fd==-
        
          1
        
        
          ){

        fprintf(stderr,
        
        
          "
        
        
          Server fifo failure\n
        
        
          "
        
        
          );

        exit(EXIT_FAILURE);

    }

    sleep(
        
        
          10
        
        
          );

    
        
        
          do
        
        
          {

        read_res
        
        =read(server_fifo_fd,&mydata,
        
          sizeof
        
        
          (mydata));

        
        
        
          if
        
        (read_res>
        
          0
        
        
          ){

            tmp_char_ptr
        
        =
        
          my_data.some_data;

            
        
        
          while
        
        (*tmp_char_ptr>
        
          0
        
        
          ){

                
        
        
          //
        
        
          把some_data中的所有字符全部轉(zhuǎn)換為大寫
        
        

                *tmp_char_ptr=toupper(*
        
          tmp_char_ptr);

                tmp_char_ptr
        
        ++
        
          ;

            }

            sprintf(client_fifo,CLIENT_FIFO_NAME,my_data.client_pid);

            client_fifo_fd
        
        =
        
          open(client_fifo,O_WRONLY);

            
        
        
          if
        
        (client_fifo_fd!=-
        
          1
        
        
          ){

                write(client_fifo_fd,
        
        &my_data,
        
          sizeof
        
        
          (my_data));

                close(client_fifo_fd);

            }

            

        }

    }
        
        
          while
        
        (read_res>
        
          0
        
        
          );

    close(server_fifo_fd);

    unlink(SERVER_FIFO_NAME);

    exit(EXIT_SUCCESS);

}
        
      

  客戶端代碼為:

        #include <unistd.h>
        
          

#include 
        
        <stdlib.h>
        
          

#include 
        
        <stdio.h>
        
          

#include 
        
        <
        
          string
        
        .h>
        
          

#include 
        
        <unistd.h>
        
          

#include 
        
        <fcntl.h>
        
          

#include 
        
        <limits.h>
        
          

#include 
        
        <sys/types.h>
        
          

#include 
        
        <sys/stat.h>
        
          

#include 
        
        <ctype.h>




        
          #define
        
         SERVER_FIFO_NAME "/tmp/serv_fifo"


        
          #define
        
         CLIENT_FIFO_NAME "/tmp/cli_%d_fifo"


        
          #define
        
         BUFFER_SIZE 20




        
          struct
        
        
           data_to_pass_st{

    pid_t client_pid;

    
        
        
          char
        
         some_data[BUFFER_SIZE-
        
          1
        
        
          ];

};




        
        
          int
        
        
           main(){

    
        
        
          int
        
        
           server_fifo_fd,client_fifo_fd;

    
        
        
          struct
        
        
           data_to_pass_st my_data;

    
        
        
          int
        
        
           times_to_send;

    
        
        
          char
        
         client_fifo[
        
          256
        
        
          ];

    

    server_fifo_fd
        
        =
        
          open(SERVER_FIFO_NAME,O_WRONLY);

    
        
        
          if
        
        (server_fifo_fd==-
        
          1
        
        
          ){

        fprintf(stderr,
        
        
          "
        
        
          Sorry,no server\n
        
        
          "
        
        
          );

        exit(EXIT_FAILURE);

    }

    my_data.client_pid
        
        =
        
          getpid();

    sprintf(client_fifo,CLIENT_FIFO_NAME,my_data.client_pid);

    
        
        
          if
        
        (mkfifo(client_fifo,
        
          0777
        
        )==-
        
          1
        
        
          ){

        fprintf(stderr,
        
        
          "
        
        
          Sorry,can't make %s\n
        
        
          "
        
        
          ,client_fifo);

        exit(EXIT_FAILURE);

    }

    
        
        
          for
        
        (times_to_send=
        
          0
        
        ;times_to_send<
        
          5
        
        ;times_to_send++
        
          ){

        sprintf(my_data.some_data,
        
        
          "
        
        
          Hello from %d
        
        
          "
        
        
          ,my_data.client_pid,my_data.some_data);

        write(server_fifo_fd,
        
        &my_data,
        
          sizeof
        
        
          (my_data));

        client_fifo_fd
        
        =
        
          open(client_fifo,O_RDONLY);

        
        
        
          if
        
        (client_fifo_fd!=-
        
          1
        
        
          ){

            
        
        
          if
        
        (read(client_fifo_fd,&my_data,
        
          sizeof
        
        (my_data))>
        
          0
        
        
          ){

                printf(
        
        
          "
        
        
          received:%s\n
        
        
          "
        
        
          ,my_data.some_data);

            }

            close(client_fifo_fd);

        }

    }

    close(server_fifo_fd);

    unlink(client_fifo);

    exit(EXIT_SUCCESS);

    

}
        
      

5 總結(jié)

???? 與管道相比,F(xiàn)IFO最大的特點就是其在文件系統(tǒng)中有fifo文件存在,這樣就可以做到進(jìn)程間通信。

6? FIFO的缺點
????? 當(dāng)然FIFO也有它的局限性。客戶端可以發(fā)請求到服務(wù)器,但前提是要知道一個公共的FIFO通道, 對于實現(xiàn)服務(wù)器回傳應(yīng)答到客戶端的問題,可以通過為每一個客戶端創(chuàng)建一個專用的FIFO,來實現(xiàn)回傳應(yīng)答 。但也有不足, 服務(wù)器會同時應(yīng)答成千上萬個客戶端,創(chuàng)建如此多的FIFO是否會使系統(tǒng)負(fù)載過大,相應(yīng)的如何判斷客戶端是否因意外而崩潰成為難題,或者客戶端不讀取應(yīng)答直接退出,所以服務(wù)器必須處理SIGPIPE信號,并做相應(yīng)處理。(當(dāng)沒有進(jìn)程為讀打開FIFO文件時,write函數(shù)進(jìn)行寫操作會產(chǎn)生SIGPIPE信號)

Linux學(xué)習(xí)筆記25——命名管道(FIFO)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 宁安市| 陕西省| 元阳县| 滨海县| 思南县| 栾川县| 合阳县| 安乡县| 双鸭山市| 家居| 翁源县| 海城市| 容城县| 大安市| 晋城| 大悟县| 建瓯市| 突泉县| 资溪县| 屯留县| 连江县| 龙江县| 神池县| 临潭县| 凉山| 临夏县| 开阳县| 徐州市| 广德县| 临夏县| 外汇| 龙口市| 青州市| 丰台区| 青河县| 张家港市| 广德县| 江都市| 贞丰县| 双鸭山市| 通城县|