一日心血来潮,想要复习进程间通信
进程间通信的方法很多,如管道、共享内存等
下面的程序在主线程执行时创建了一个名为 listener 的监听线程
主线程从用户获取输入,监听线程监听主线程获取的输入,用红色字体打印到终端上
主线程和监听线程之间,通过命名管道 "fifo_file" 通信
代码(已验证可执行)
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
void listen_handler();
int main(){
char c;
int ret;
char str[BUFSIZ] = {0};
int len;
const char* fifo_path="./fifo_file";
int fd;
pthread_t listener;
if(-1 == mkfifo(fifo_path, 0777)){
printf("client create fifo file:%s failed.\n", fifo_path);
perror("mkfifo failed");
}else{
printf("client create fifo file:%s successed.\n", fifo_path);
}
fd = open(fifo_path, O_RDWR|O_NONBLOCK);
if (0 != ret){
printf("open fifo file failed.\n");
return 0;
}else{
printf("open fifo file successed.\n");
}
ret = pthread_create(&listener, NULL, listen_handler, NULL);
if (0 != ret){
printf("create thread failed.\n");
return 0;
}
ret = pthread_detach(listener);
if (0 != ret){
printf("detach thread failed.\n");
return 0;
}
printf("client started.\n");
printf("press q to quit.\n");
while(1){
//gets(str, BUFSIZ);
len = getline(&str, &len, stdin);
len = strlen(str);
printf("client get line of length %d: %s\n", len, str);
if('q' == str[0]){
break;
}
if(-1 == write(fd, str, len)){
perror("write data error:");
}
}
close(fd);
return 0;
}
void listen_handler(){
char msg[BUFSIZ] = {0};
int fd;
int ret;
const char* fifo_path="./fifo_file";
printf("\033[41;1mserver is listening...\033[0m\n");
if(-1 == mkfifo(fifo_path, 0777)){
printf("listneer create fifo file:%s failed.\n", fifo_path);
}else{
printf("listener create fifo file:%s successed.\n", fifo_path);
}
fd = open(fifo_path, O_RDONLY);
if(-1 == fd){
printf("open fifo %s failed.\n", fifo_path);
return;
}else{
printf("open fifo file successed.\n");
}
while(1){
if(-1 != read(fd, msg, BUFSIZ)){
printf("\033[41;1mreceive data: %s\033[0m\n", msg);
}else{
perror("read data error:");
}
}
printf("end of listener.\n");
}
主要参考:
命名管道 mkfifo
https://www.cnblogs.com/52php/p/5840229.html
进程间通信
https://www.cnblogs.com/CheeseZH/p/5264465.html
pthread
https://blog.csdn.net/weibo1230123/article/details/81410241
用到的函数
open
read
write
perror(调试用)
pthread_create
pthread_detach(不等待线程执行完毕)
注意点
若出现write data failed: Bad file descriptor
则是因为文件创建时候的权限和文件open时候的权限不一致
open时候的选项:
O_RDWR
O_RDONLY
O_WRONLY
O_NONBLOCK
mkfifo时候
0777
0666
若出现open后无反应,则需要查看open是否添加了非阻塞选项
O_NONBLOCK非阻塞
选项 O_NONBLOCK 表示非阻塞,加上这个选项后,表示open调用是非阻塞的,如果没有这个选项,则表示open调用是阻塞的。
open调用的阻塞是什么一回事呢?很简单,对于以只读方式(O_RDONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_RDONLY),除非有一个进程以写方式打开同一个FIFO,否则它不会返回;如果open调用是非阻塞的的(即第二个参数为O_RDONLY | O_NONBLOCK),则即使没有其他进程以写方式打开同一个FIFO文件,open调用将成功并立即返回。
对于以只写方式(O_WRONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_WRONLY),open调用将被阻塞,直到有一个进程以只读方式打开同一个FIFO文件为止;如果open调用是非阻塞的(即第二个参数为O_WRONLY | O_NONBLOCK),open总会立即返回,但如果没有其他进程以只读方式打开同一个FIFO文件,open调用将返回-1,并且FIFO也不会被打开。
pthread_detach vs pthread_join
pthread_join()即是子线程合入主线程,主线程阻塞等待子线程结束,然后回收子线程资源。
pthread_detach()即主线程与子线程分离,子线程结束后,资源自动回收。
pthread非系统默认库,需要编译时候链接
gcc main.c -lpthread