Linux系統程式設計之程式間通訊方式:命名管道(二)

千鋒教育官方發表於2019-09-12

  

  命名管道的預設操作

 

  2)假如FIFO裡沒有資料,呼叫read()函式從FIFO裡讀資料時read()也會阻塞。這個特點和無名管道是一樣的。

 

  寫端程式碼如下:

 

  #include<stdio.h>

 

  #include<string.h>

 

  #include<unistd.h>

 

  #include<sys/types.h>

 

  #include<sys/stat.h>

 

  #include<fcntl.h>

 

  int main(int argc,char*argv[])

 

  {

 

  int fd;

 

  int ret;

 

  ret=mkfifo("my_fifo",0666);//建立命名管道

 

  if(ret!=0)

 

  {

 

  perror("mkfifo");

 

  }

 

  printf("before open\n");

 

  fd=open("my_fifo",O_WRONLY);//等著只讀

 

  if(fd<0)

 

  {

 

  perror("open fifo");

 

  }

 

  printf("after open\n");

 

  printf("before write\n");

 

  //5s後才往命名管道寫資料,沒資料前,讀端read()阻塞

 

  sleep(5);

 

  char send[100]="Hello Mike";

 

  write(fd,send,strlen(send));

 

  printf("write to my_fifo buf=%s\n",send);

 

  return 0;

 

  }

 

  讀端程式碼如下:

 

  #include<stdio.h>

 

  #include<string.h>

 

  #include<unistd.h>

 

  #include<sys/types.h>

 

  #include<sys/stat.h>

 

  #include<fcntl.h>

 

  int main(int argc,char*argv[])

 

  {

 

  int fd;

 

  int ret;

 

  ret=mkfifo("my_fifo",0666);//建立命名管道

 

  if(ret!=0)

 

  {

 

  perror("mkfifo");

 

  }

 

  printf("before open\n");

 

  fd=open("my_fifo",O_RDONLY);//等著只寫

 

  if(fd<0)

 

  {

 

  perror("open fifo");

 

  }

 

  printf("after open\n");

 

  printf("before read\n");

 

  char recv[100]={0};

 

  //讀資料,命名管道沒資料時會阻塞,有資料時就取出來

 

  read(fd,recv,sizeof(recv));

 

  printf("read from my_fifo buf=[%s]\n",recv);

 

  return 0;

 

  }

 

  請根據下圖自行編譯執行驗證:

 

  3)通訊過程中若寫程式先退出了,就算命名管道里沒有資料,呼叫read()函式從FIFO裡讀資料時不阻塞;若寫程式又重新執行,則呼叫read()函式從FIFO裡讀資料時又恢復阻塞。

 

  寫端程式碼如下:

 

  #include<stdio.h>

 

  #include<string.h>

 

  #include<unistd.h>

 

  #include<sys/types.h>

 

  #include<sys/stat.h>

 

  #include<fcntl.h>

 

  int main(int argc,char*argv[])

 

  {

 

  int fd;

 

  int ret;

 

  ret=mkfifo("my_fifo",0666);//建立命名管道

 

  if(ret!=0)

 

  {

 

  perror("mkfifo");

 

  }

 

  fd=open("my_fifo",O_WRONLY);//等著只讀

 

  if(fd<0)

 

  {

 

  perror("open fifo");

 

  }

 

  char send[100]="Hello Mike";

 

  write(fd,send,strlen(send));//寫資料

 

  printf("write to my_fifo buf=%s\n",send);

 

  while(1);//阻塞,保證讀寫程式保持著通訊過程

 

  return 0;

 

  }

 

  讀端程式碼如下:

 

  #include<stdio.h>

 

  #include<string.h>

 

  #include<unistd.h>

 

  #include<sys/types.h>

 

  #include<sys/stat.h>

 

  #include<fcntl.h>

 

  int main(int argc,char*argv[])

 

  {

 

  int fd;

 

  int ret;

 

  ret=mkfifo("my_fifo",0666);//建立命名管道

 

  if(ret!=0)

 

  {

 

  perror("mkfifo");

 

  }

 

  fd=open("my_fifo",O_RDONLY);//等著只寫

 

  if(fd<0)

 

  {

 

  perror("open fifo");

 

  }

 

  while(1)

 

  {

 

  char recv[100]={0};

 

  read(fd,recv,sizeof(recv));//讀資料

 

  printf("read from my_fifo buf=[%s]\n",recv);

 

  sleep(1);

 

  }

 

  return 0;

 

  }

 

  請根據下圖自行編譯執行驗證:

 

 

  5)通訊過程中,讀程式退出後,寫程式向命名管道內寫資料時,寫程式也會(收到SIGPIPE訊號)退出。

 

  6)呼叫write()函式向FIFO裡寫資料,當緩衝區已滿時write()也會阻塞。

 

  5)和6)這兩個特點和無名管道是一樣的,這裡不再驗證,詳情請看《無名管道》。

 

  命名管道非阻塞標誌操作

 

  命名管道可以以非阻塞標誌(O_NONBLOCK)方式開啟:

 

  fd=open("my_fifo",O_WRONLY|O_NONBLOCK);

 

  fd=open("my_fifo",O_RDONLY|O_NONBLOCK);

 

  非阻塞標誌(O_NONBLOCK)開啟的命名管道有以下特點:

 

  1、先以只讀方式開啟,如果沒有程式已經為寫而開啟一個FIFO,只讀open()成功,並且open()不阻塞。

 

  2、先以只寫方式開啟,如果沒有程式已經為讀而開啟一個FIFO,只寫open()將出錯返回-1。

 

  3、read()、write()讀寫命名管道中讀資料時不阻塞。

 

  請根據以下程式碼自行編譯執行驗證。

 

  寫端程式碼如下:

 

  #include<stdio.h>

 

  #include<string.h>

 

  #include<unistd.h>

 

  #include<sys/types.h>

 

  #include<sys/stat.h>

 

  #include<fcntl.h>

 

  int main(int argc,char*argv[])

 

  {

 

  int fd;

 

  int ret;

 

  ret=mkfifo("my_fifo",0666);//建立命名管道

 

  if(ret!=0)

 

  {

 

  perror("mkfifo");

 

  }

 

  //只寫並指定非阻塞方式開啟

 

  fd=open("my_fifo",O_WRONLY|O_NONBLOCK);

 

  if(fd<0)

 

  {

 

  perror("open fifo");

 

  }

 

  char send[100]="Hello Mike";

 

  write(fd,send,strlen(send));

 

  printf("write to my_fifo buf=%s\n",send);

 

  while(1);

 

  return 0;

 

  }

 

  讀端程式碼如下:

 

  #include<stdio.h>

 

  #include<string.h>

 

  #include<unistd.h>

 

  #include<sys/types.h>

 

  #include<sys/stat.h>

 

  #include<fcntl.h>

 

  int main(int argc,char*argv[])

 

  {

 

  int fd;

 

  int ret;

 

  ret=mkfifo("my_fifo",0666);//建立命名管道

 

  if(ret!=0)

 

  {

 

  perror("mkfifo");

 

  }

 

  //只讀並指定非阻塞方式開啟

 

  fd=open("my_fifo",O_RDONLY|O_NONBLOCK);

 

  if(fd<0)

 

  {

 

  perror("open fifo");

 

  }

 

  while(1)

 

  {

 

  char recv[100]={0};

 

  read(fd,recv,sizeof(recv));

 

  printf("read from my_fifo buf=[%s]\n",recv);

 

  sleep(1);

 

  }

 

  return 0;

 

  }


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69914734/viewspace-2656894/,如需轉載,請註明出處,否則將追究法律責任。

相關文章