Linux 進程間通訊 ①

無名管道pipe

  • 半雙工的通訊模式
  • 只能在具有親緣關係的進程間通訊,即只能在父進程與子進程之間進行通訊

pipe函數int pipe(int pipefd[2])
參數pipefd[0]:用於讀管道
參數pipefd[1]:用於寫管道
返回值:執行成功返回0, 失敗返回-1

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

void read_data(int *);          //讀進程函數
void write_data(int *);         //寫進程函數

int main(int argc, char *argv[])
{
    int pipes[2], rc;   
    pid_t pid;

    rc = pipe(pipes);           //創建管道
    if(rc == -1)
    {
        perror("\npipes\n");
        exit(1);
    }

    pid = fork();       //創建進程

    switch(pid)         //通過判斷pid來使父進程和子進程進入不同的函數
    {
        case -1:
            perror("\n fork!\n");
            exit(1);
        case 0:
            read_data(pipes);
        default:
            write_data(pipes);
    }
    return 0;
}

void read_data(int pipes[])
{
    int c, rc;
    close(pipes[1]);                        //此函數只讀,所以關閉寫描述

    //阻塞 等待從管道讀取數據
    while((rc = read(pipes[0], &c, 1))>0)   //int轉換爲unsigned char輸出到終端
    {
        putchar(c);
    }
    exit(0);
}

void write_data(int pipes[])
{
    int c, rc;
    close(pipes[0]);                        //此函數只寫,所以關閉讀描述

    while((c = getchar()) >0 )
    {
        rc = write(pipes[1], &c, 1);
        if( rc == -1)
        {
            perror("Parent:write");
            close(pipes[1]);
            exit(1);
        }
    }
    close(pipes[1]);
    exit(0);
}

有名管道fifo

  • 可以實現無親緣關係的進程間通訊
  • 有名管道FIFO給文件系統提供一個路徑,只要知道這個路徑,就可以訪問這個管道
  • FIFO指先進先出
  • 有名管道讀取速度非常快

創建有名管道函數
mkfifo(const char *pathname, mode_t mode)
*參數 pathname:路徑名,管道名稱
參數 mode:管道的權限
返回值:成功返回0,錯誤返回-1

有名管道的讀/寫操作
向有名管道中讀取/寫入數據與文件的讀寫操作時一樣的,先要定義fifo的名稱和打開方式,然後打開fifo獲取到其句柄,再使用寫函數對其進行讀/寫操作。

	const char *fifo_name = "my_fifo";          //定義FIFO名稱
	int fifo_fd = -1;                           //fifo句柄
	char buffer[PIPE_BUF+1];                    //buffer的大小,PIPE_BUF爲有名管道中的一個常量

	fifo_fd = open(fifo_name, O_WRONLY);       //以阻塞方式打開數據fifo文件
	
	write(fifo_fd, buffer, bytes_read);       //向fifo寫入數據
	read(pipe_fd, buffer, PIPE_BUF);	//從fifo中讀取數據

消息隊列msg

消息隊列就是一個消息的鏈表。可以把消息看作一個記錄,具有特定的格式以及特定的優先級。對消息隊列有寫權限的進程可以向其中按照一定的規則添加新消息;對消息隊列有讀權限的進程則可以從消息隊列中讀走消息。

消息隊列接收函數

 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);

參數 msqid:消息隊列的標識碼
參數*msgp:指向消息緩衝區的指針
參數 msgsz:消息的長短
參數 msgflg:標誌位
返回值:成功返回數據長度,錯誤返回-1

消息隊列發送函數

 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

參數 msqid:消息隊列的標識碼
參數*msgp:指向消息緩衝區的指針,此位置用來暫時存儲發送和接收的消息,是一個用戶可定義的通用結構
參數 msgsz:消息的長短
參數 msgflg:標誌位
返回值:成功返回 0,錯誤返回-1

其中的結構體 msgp,是一個標準的通用結構,如下所示。

struct msgstru
{
	long mtype; 				//大於 0
	char mtext[nbyte];
};

獲取與某個鍵“key”關聯的消息隊列標識

int msgget(key_t key, int msgflg)

參數“key”:消息隊列關聯的鍵。
參數“msgflg”:消息隊列的建立標誌和存取權限。IPC_CREAT 如果內核中沒有此隊列,則創建它;IPC_EXCL 當和 IPC_CREAT 一起使用時,如果隊列已經存在,則失敗。
返回值:執行成功則返回消息隊列的標識符,否則返回-1。

#define MAX_TEXT 512			
struct msg_st									//定義結構體
{
    long int msg_type;
    char text[MAX_TEXT];
};
	...

    struct msg_st data;
    char buffer[BUFSIZ];
    int msgid = -1;
    ...
    msgid = msgget((key_t)1234, 0666 | IPC_CREAT);              //建立消息隊列 在不同的函數中,如果要使用同一個消息隊列,獲取消息隊列標識時key_t的值要一致。
	...
	msgsnd(msgid, (void*)&data, MAX_TEXT, 0)		//發送
	...
	(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0)	//接收
	...

信號signal

sighandler_t signal(int signum, sighandler_t handler);

參數 signum:等待的信號
參數 handler:信號到來之後,觸發的處理方式
返回值:成功返回 0,錯誤返回-1

signum的信號列表如下

SIGABRT        進程停止運行    6
SIGALRM        警告鍾    
SIGFPE        算述運算例外
SIGHUP        系統掛斷
SIGILL        非法指令
SIGINT        終端中斷   2
SIGKILL        停止進程(此信號不能被忽略或捕獲)
SIGPIPE        向沒有讀的管道寫入數據
SIGSEGV        無效內存段訪問
SIGQOUT        終端退出    3
SIGTERM        終止
SIGUSR1        用戶定義信號1
SIGUSR2        用戶定義信號2
SIGCHLD        子進程已經停止或退出
SIGCONT        如果被停止則繼續執行
SIGSTOP        停止執行
SIGTSTP        終端停止信號
SIGTOUT        後臺進程請求進行寫操作
SIGTTIN        後臺進程請求進行讀操作
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void handler()
{
    printf("Hello Signal!\n");     
}


int main()
{
	signal(SIGALRM, handler);       //接收到信號就執行handler函數
    alarm(5);                  			     //定時5秒後alarm會發出信號
    return 0;  
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章