1. 程式人生 > >linux 程序通訊——C語言實現

linux 程序通訊——C語言實現

       linux中的程序通訊分為三個部分:低階通訊,管道通訊和程序間通訊IPC(inter process communication)。linux的低階通訊主要用來傳遞程序的控制訊號——檔案鎖和軟中斷訊號機制。linux的程序間通訊IPC有三個部分——①訊號量,②共享記憶體和③訊息佇列。以下是我編寫的linux程序通訊的C語言實現程式碼。作業系統為redhat9.0,編輯器為vi,編譯器採用gcc。下面所有實現程式碼均已經通過測試,執行無誤。

一.低階通訊--訊號通訊

signal.c

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

/*捕捉到訊號sig之後,執行預先預定的動作函式*/
void sig_alarm(int sig)
{
 printf("---the signal received is %d. /n", sig);
 signal(SIGINT, SIG_DFL); //SIGINT終端中斷訊號,SIG_DFL:恢復預設行為,SIN_IGN:忽略訊號
}

int main()
{
 signal(SIGINT, sig_alarm);//捕捉終端中斷訊號

 while(1)
 {
  printf("waiting here!/n");
  sleep(1);
 }
 return 0;
}

二.管道通訊

pipe.c

#include <stdio.h>

#define BUFFER_SIZE 30


int main()
{
 int x;
 int fd[2];
 char buf[BUFFER_SIZE];
 char s[BUFFER_SIZE];
 pipe(fd);//建立管道

 while((x=fork())==-1);//建立管道失敗時,進入迴圈
 
 /*進入子程序,子程序向管道中寫入一個字串*/
 if(x==0)
 {
  sprintf(buf,"This is an example of pipe!/n");
  write(fd[1],buf,BUFFER_SIZE);
  exit(0);
 }

 /*進入父程序,父程序從管道的另一端讀出剛才寫入的字串*/
 else
 {
  wait(0);//等待子程序結束
  read(fd[0],s,BUFFER_SIZE);//讀出字串,並將其儲存在char s[]中
  printf("%s",s);//列印字串
 }
 return 0;
}

三.程序間通訊——IPC

①訊號量通訊

sem.c

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

/*聯合體變數*/
union semun
{
 int val; //訊號量初始值                  
 struct semid_ds *buf;       
 unsigned short int *array; 
 struct seminfo *__buf;     
};

/*函式宣告,訊號量定義*/
static int set_semvalue(void); //設定訊號量
static void del_semvalue(void);//刪除訊號量
static int semaphore_p(void);  //執行P操作
static int semaphore_v(void);  //執行V操作
static int sem_id;             //訊號量識別符號

int main(int argc, char *argv[])
{
 int i;
 int pause_time;
 char op_char = 'O';
 srand((unsigned int)getpid()); 
 sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT);//建立一個訊號量,IPC_CREAT表示建立一個新的訊號量
 
 /*如果有引數,設定訊號量,修改字元*/
 if (argc > 1)
 {
  if (!set_semvalue())
  {
   fprintf(stderr, "Failed to initialize semaphore/n");
   exit(EXIT_FAILURE);
  }
  op_char = 'X';
  sleep(5);
 }

 for(i = 0; i < 10; i++)  
 {      


  /*執行P操作*/
  if (!semaphore_p())
   exit(EXIT_FAILURE);

  printf("%c", op_char);
  fflush(stdout);
  pause_time = rand() % 3;
  sleep(pause_time);
  printf("%c", op_char);
  fflush(stdout);

  /*執行V操作*/
  if (!semaphore_v())
   exit(EXIT_FAILURE);

  pause_time = rand() % 2;
  sleep(pause_time);
 }  
 printf("/n%d - finished/n", getpid());

 if (argc > 1)
 {   
  sleep(10);
  del_semvalue(); //刪除訊號量
 }   
 exit(EXIT_SUCCESS);
}

/*設定訊號量*/
static int set_semvalue(void)
{
 union semun sem_union;
 sem_union.val = 1;
 if (semctl(sem_id, 0, SETVAL, sem_union) == -1)
  return(0);
 
 return(1);
}

/*刪除訊號量*/
static void del_semvalue(void)
{
 union semun sem_union; 
 if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
  fprintf(stderr, "Failed to delete semaphore/n");
}

/*執行P操作*/
static int semaphore_p(void)
{
 struct sembuf sem_b;  
 sem_b.sem_num = 0;
 sem_b.sem_op = -1; /* P() */
 sem_b.sem_flg = SEM_UNDO;
 if (semop(sem_id, &sem_b, 1) == -1)
 {
  fprintf(stderr, "semaphore_p failed/n");
  return(0);
 }
 return(1);
}


/*執行V操作*/
static int semaphore_v(void)
{
 struct sembuf sem_b;
 sem_b.sem_num = 0;
 sem_b.sem_op = 1; /* V() */
 sem_b.sem_flg = SEM_UNDO;
 if (semop(sem_id, &sem_b, 1) == -1)
 {
  fprintf(stderr, "semaphore_v failed/n");
  return(0);
 }
 return(1);
}

②訊息佇列通訊

send.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_TEXT 512

/*用於訊息收發的結構體--my_msg_type:訊息型別,some_text:訊息正文*/
struct my_msg_st
{
 long int my_msg_type;
 char some_text[MAX_TEXT];
};

int main()
{
 int running = 1;//程式執行識別符號
 struct my_msg_st some_data;
 int msgid;//訊息佇列識別符號
 char buffer[BUFSIZ];

 /*建立與接受者相同的訊息佇列*/
 msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
 if (msgid == -1)
 {
  fprintf(stderr, "msgget failed with error: %d/n", errno);
  exit(EXIT_FAILURE);
    }

 /*向訊息佇列中傳送訊息*/
 while(running)
 {
  printf("Enter some text: ");
  fgets(buffer, BUFSIZ, stdin);
  some_data.my_msg_type = 1;
  strcpy(some_data.some_text, buffer);
  if (msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1)
  {
   fprintf(stderr, "msgsnd failed/n");
   exit(EXIT_FAILURE);
  }
  if (strncmp(buffer, "end", 3) == 0)
  {
   running = 0;
  }
 }
 exit(EXIT_SUCCESS);
}

receive.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

/*用於訊息收發的結構體--my_msg_type:訊息型別,some_text:訊息正文*/
struct my_msg_st
{
 long int my_msg_type;
 char some_text[BUFSIZ];
};

int main()
{
 int running = 1;//程式執行識別符號
 int msgid; //訊息佇列識別符號
 struct my_msg_st some_data;
 long int msg_to_receive = 0;//接收訊息的型別--0表示msgid佇列上的第一個訊息

 /*建立訊息佇列*/
 msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
 if (msgid == -1)
 {
  fprintf(stderr, "msgget failed with error: %d/n", errno);
  exit(EXIT_FAILURE);
 }

 /*接收訊息*/
 while(running)
 {
  if (msgrcv(msgid, (void *)&some_data, BUFSIZ,msg_to_receive, 0) == -1)
  {
   fprintf(stderr, "msgrcv failed with error: %d/n", errno);
   exit(EXIT_FAILURE);
  }
  printf("You wrote: %s", some_data.some_text);
  if (strncmp(some_data.some_text, "end", 3) == 0)
  {
   running = 0;
  }
 }

 /*刪除訊息佇列*/
 if (msgctl(msgid, IPC_RMID, 0) == -1)
 {
  fprintf(stderr, "msgctl(IPC_RMID) failed/n");
  exit(EXIT_FAILURE);
 }
 exit(EXIT_SUCCESS);
}

③共享記憶體通訊

share.h

#define TEXT_SZ 2048 //申請共享記憶體大小

struct shared_use_st
{
 int written_by_you; //written_by_you為1時表示有資料寫入,為0時表示資料已經被消費者提走
 char some_text[TEXT_SZ];
};

producer.c

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "share.h"


int main()
{
 int running = 1; //程式執行標誌位
 void *shared_memory = (void *)0;
 struct shared_use_st *shared_stuff;
 char buffer[BUFSIZ];
 int shmid; //共享記憶體識別符號

 /*建立共享記憶體*/
 shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);
 if (shmid == -1)
 {
  fprintf(stderr, "shmget failed/n");
  exit(EXIT_FAILURE);
 }

 /*將共享記憶體連線到一個程序的地址空間中*/
 shared_memory = shmat(shmid, (void *)0, 0);//指向共享記憶體第一個位元組的指標
 if (shared_memory == (void *)-1)
 {
  fprintf(stderr, "shmat failed/n");
  exit(EXIT_FAILURE);
 }

 printf("Memory attached at %X/n", (int)shared_memory);
 shared_stuff = (struct shared_use_st *)shared_memory;

 /*生產者寫入資料*/
 while(running)
 {
  while(shared_stuff->written_by_you == 1)
  {
   sleep(1);           
   printf("waiting for client.../n");
  }
  printf("Enter some text: ");
  fgets(buffer, BUFSIZ, stdin);
  strncpy(shared_stuff->some_text, buffer, TEXT_SZ);
  shared_stuff->written_by_you = 1;
  if (strncmp(buffer, "end", 3) == 0)
  {
   running = 0;
  }
 }

    /*該函式用來將共享記憶體從當前程序中分離,僅使得當前程序不再能使用該共享記憶體*/
 if (shmdt(shared_memory) == -1)
 {
  fprintf(stderr, "shmdt failed/n");
  exit(EXIT_FAILURE);
 }

 printf("producer exit./n");
 exit(EXIT_SUCCESS);
}

customer.c

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "share.h"


int main()
{
 int running = 1;//程式執行標誌位
 void *shared_memory = (void *)0;
 struct shared_use_st *shared_stuff;
 int shmid; //共享記憶體識別符號
 srand((unsigned int)getpid());   

 /*建立共享記憶體*/
 shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);
 if (shmid == -1)
 {
  fprintf(stderr, "shmget failed/n");
  exit(EXIT_FAILURE);
 }

 /*將共享記憶體連線到一個程序的地址空間中*/
 shared_memory = shmat(shmid, (void *)0, 0);//指向共享記憶體第一個位元組的指標
 if (shared_memory == (void *)-1)
 {
  fprintf(stderr, "shmat failed/n");
  exit(EXIT_FAILURE);
 }

 printf("Memory attached at %X/n", (int)shared_memory);
 shared_stuff = (struct shared_use_st *)shared_memory;
 shared_stuff->written_by_you = 0;

 /*消費者讀取資料*/
 while(running)
 {
  if (shared_stuff->written_by_you)
  {
   printf("You wrote: %s", shared_stuff->some_text);
   sleep( rand() % 4 ); 
   shared_stuff->written_by_you = 0;
   if (strncmp(shared_stuff->some_text, "end", 3) == 0)
   {
    running = 0;
   }
  }
 }

 /*該函式用來將共享記憶體從當前程序中分離,僅使得當前程序不再能使用該共享記憶體*/
 if (shmdt(shared_memory) == -1)
 {
  fprintf(stderr, "shmdt failed/n");
  exit(EXIT_FAILURE);
 }

 /*將共享記憶體刪除,所有程序均不能再訪問該共享記憶體*/
 if (shmctl(shmid, IPC_RMID, 0) == -1)
 {
  fprintf(stderr, "shmctl(IPC_RMID) failed/n");
  exit(EXIT_FAILURE);
 }

 exit(EXIT_SUCCESS);
}

相關推薦

linux 程序通訊——C語言實現

       linux中的程序通訊分為三個部分:低階通訊,管道通訊和程序間通訊IPC(inter process communication)。linux的低階通訊主要用來傳遞程序的控制訊號——檔案鎖和軟中斷訊號機制。linux的程序間通訊IPC有三個部分——①訊號量,②共

Linux終端程序c語言實現改變輸出的字的顏色

光標位置 高亮 AI 藍色 屬性 用c語言實現 TE c語言 說明 顏色代碼: 格式: echo "\033[字背景顏色;字體顏色m字符串\033[0m" 例如: echo "\033[41;36m something here \033[0m" 其中41的位置代表

Word Count程序C語言實現

地址 組成 other 進一步 and 文件遍歷 stand evel oid Word Count 程序 GitHub地址:https://github.com/MansonYe/Word-Count 一、項目簡介 Word Count 是用以統計文本文件的字符數

Linux下用c語言實現發送http請求 方式可以Get或者Post例程參考

sockaddr select sleep online 創建 線程終止 index -s lse [1].[代碼] Linux下用c語言實現發送http請求 方式可以Get或者Post 跳至 [1] ? 1 2 3 4 5 6 7 8 9 10 11 12 1

Linux下用c語言實現傳送http請求 方式可以Get或者Post例程參考

[1].[程式碼] Linux下用c語言實現傳送http請求 方式可以Get或者Post 跳至 [1] ? 1 2

Linux下用c語言實現傳送http請求

前言 在linux下,使用socket進行程式設計,需要到伺服器上進行獲取資料,伺服器使用的php程式設計,需要使用http的方式進行獲取資料。 程式碼 #include <stdio.h> #include <string.h&

linux 環境下 c語言實現mysql資料庫圖片的儲存以及多資料庫直接的轉存

作為一個程式設計師,CSDN對我的程式設計帶來了很多幫助和提高,在這裡可以讓你找到很多開發過程中遇到的問題的解決辦法,今天也寫點自己積累的東西跟大家分享一下,希望對需要的人有幫助. 資料背景:         之前專案一直使用Oracle資料,最近換工作,公司使用的為

linux環境下C語言實現非阻塞方式讀取字串資料的串列埠測試程式,即串列埠工具的編寫

一、前言 1.1 關於串列埠測試工具,網上已經有整合好的應用程式提供大家使用,但其只提供功能介面,內部具體怎麼實現的還需要自己去探索; 1.2 關於串列埠通訊的測試程式在網上已經是數見不鮮,但也不排除很多是直接“參考”別人的(ctrl+c),而且很多程式

linux下使用C語言實現簡易的學生資訊管理系統

該專案資料儲存方式使用的是動態陣列,所以需要用到動態陣列庫,具體庫檔案參考->我的動態陣列庫<-上的兩個檔案 ArrayLib.h 和 ArrayLib.c 學生管理系統的檔案有三個 main.c、stuSystem.h 和 stuSystem.c,

linux下使用C語言實現比較漂亮的字元介面的五子棋遊戲

此專案總共檔案3個檔案 main.c、fiveChess.h 和 fiveChess.c,需要放到同一目錄下編譯 main.c /******************************************************* * 檔名: ma

C語言實現串列埠通訊知識點整理(四)】關於執行緒和程序

轉載:https://www.cnblogs.com/fuchongjundream/p/3829508.html 因為在外部檔案中呼叫結構體沒有用extern修飾,導致獲取不到正確的值,一直糾結線上程上。現在大概總結執行緒和程序的特點: 概念 1、程序(process) 狹義定義:

linux中編譯C語言程序

編輯器 ins spa include all 運行程序 gcc linux中 style 1.首先安裝gcc編輯器 yum install gcc* -y 2.編寫C語言程序 [[email protected]/* */ ~]# vim aa.c #i

C語言實現24點程序

項目 四則運算 return 輸出 存儲 數據 value class 教材 一、簡介 本程序的思想和算法來自於C語言教材後的實訓項目,程序通過用戶輸入四個整數計算出能夠通過加減乘除得到數字24的所有表達式,程序的設計有別於一般

C語言實現的圖的深度搜索與廣度搜索程序

scan 實現 圖的鄰接表存儲 class dfs c語言 return 並查集 OS /* 上機試驗5-圖的建立和遍歷 1)建立【無向】【非連通】圖的鄰接表存儲結構,要求頂點個數不少於15個。 2)用DFS及BFS對此鄰接表進行遍歷,打印出兩種遍歷的頂點訪問順序。 3)給

c語言實現linux下高危函式system (簡易V1.0版本)

system這個函式真的是要慎用,一不小心就會留下漏洞。 下面是用c語言簡易的實現了一下system函式 #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<err

(排序演算法)linux c語言實現選擇排序演算法(氣泡排序的略微改進版)

 快速排序演算法和氣泡排序演算法是差不多的,都是要兩層迴圈,外迴圈是要比較的個數,其實就是元素的個數,內迴圈就是外層那個標記和其他的比較大小, 氣泡排序是相鄰的兩個,兩兩比較,最後交換出一個最大或者最小值, 快速排序是在氣泡排序的基礎上,找出那個最小的或者最大的,但是不是直接交換,

(排序演算法)linux c語言實現快速排序(氣泡排序的改進版)

 快速排序演算法是對氣泡排序演算法的一種改進,氣泡排序是對單個元素的升降,快速排序是對所有元素的升降,不過這個升降是取了某一個標準的前提下,在本文程式碼中,就以a[i],其實就是以最左邊的元素為參考,比較交換之後,將這個參考元素放到分界的地方,即i的位置。 程式碼如下,裡面有比較詳細的

(排序演算法)linux c語言實現二分插入排序演算法(簡化版本的插入排序演算法)

 二分插入演算法是在已經排序好的序列裡插入一個元素,是穩定的演算法,關鍵詞是折中。 比如說我要在12345678910裡插入一個3,那麼我先看看中間的數比3大,還是比3小,要是比3大,我就去後一半,如果是比3小,我就去前一半,現在進入某個一半後,再做如此操作,最後將其他的元素依次往後挪

C語言實現串列埠通訊知識點整理(三)】串列埠開啟、設定資料成功後進行資料讀寫

int OpenDev(char *Dev) { int fd = open(Dev,O_RDWR | O_NOCTTY | O_NONBLOCK); if(-1 == fd) { perror("Can't Open Serial Port"); return -1;

C語言實現串列埠通訊知識點整理(二)】遇到的問題整理(待續....)

1.c編譯錯誤--error:stray \357 in program UTF-8編碼問題。UTF-8編碼有BOM和無BOM格式。BOM,ByteOrderMark(位元組標記順序),表明使用UTF8來進行編碼。UTF-8的BOM通常為3個位元組EF BB BF。轉換成對應的字元檢視,就是‘\