無名管道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;
}