这一节主要是讲有名管道

有名管道的特点是它保证了写入原子性,而且可用于无亲缘关系的任意进程,它是创建在某个路径下,所以当进程退出时它也不会消失,而无名管道是创建在内存中,所以进程退出时候它就消失了。进程利用有名管道通信需要用到双线程,一个线程用于读,一个线程用于写。

下图是有名管道与无名管道的区别:

系统编程七

程序:

//写进程

#define FIFONAME "myfifo"
#define SIZE 100

int main(int argc, char **argv)
{
// NOT exist
if(access(FIFONAME, F_OK))  //判断是否有这个文件,没有就创建这个管道,因为通信双方此时并不知道有没   //创建管道,先运行的先创建管道
{
mkfifo(FIFONAME, 0777);
}


int fd = open(FIFONAME, O_RDWR);

char buf[SIZE];
while(1)
{
bzero(buf, SIZE);
fgets(buf, SIZE, stdin);

write(fd, buf, strlen(buf));
}
close(fd);

return 0;
}


//读进程

int main(int argc, char **argv)
{
// NOT exist
if(access(FIFONAME, F_OK))
{
mkfifo(FIFONAME, 0777);
}

int fd = open(FIFONAME, O_RDONLY);

char buf[SIZE];
while(1)
{
bzero(buf, SIZE);
read(fd, buf, SIZE);

printf("from Jack: %s", buf);
}
close(fd);

return 0;
}


有名管道的使用

有名管道最经典的用法是守护进程创建有名管道并且和日志系统沟通。对于普通文件,一旦有多个进程来访问经常会通过加锁或者信号量来约束信息,以保证不会乱。但是加锁或者信号量只能适用于一个程序里面的多个进程,但不适用于多个程序,明显的访问日志系统通常不是同一个程序里面的多个进程。所以这里就不能用互斥锁来规范了。此时可以用有名管道,因为有名管道保证了写入原子性。这个守护进程还提供了一些接口文件(syslog,openlog)给上层调用,上面的进程只知道调用接口就能访问日志文件,而其实是通过有名管道来访问日志文件。

系统编程七

另外要注意的是open()是一个阻塞函数,一直到这个管道有读者和写者。

一般情况下(没有指定O_NONBLOCK),只读open要阻塞到某个其他进程为写而打开这个FIFO为止。类似的,只写open要阻塞到某个其他进程为读而打开它为止,所以我们一般打开的时候就用可读可写方式打开。

程序:

//server

int main(int argc, char **argv)
{
int logfd = open("mylog", O_CREAT | O_WRONLY, 0644);
mkfifo("fifo", 0666);

int fifofd = open("fifo", O_RDWR);   //以可读可写方式打开
char buf[SIZE];
while(1)
{
bzero(buf, SIZE);
read(fifofd, buf, SIZE);
write(logfd, buf, strlen(buf));
}
return 0;
}


//client

int main(int argc, char **argv)
{
char msg[SIZE];
time_t t;

int fifofd = open("fifo", O_WRONLY);

while(1)
{
bzero(msg, SIZE);
time(&t);
snprintf(msg, SIZE, "[%d] %s", getpid(), ctime(&t));
write(fifofd, msg, strlen(msg));
sleep(1);
}
return 0;
}


相关文章:

  • 2021-04-25
  • 2021-07-01
  • 2021-06-14
  • 2021-12-08
  • 2021-10-23
  • 2022-12-23
  • 2022-01-09
猜你喜欢
  • 2021-07-11
  • 2021-05-27
  • 2021-10-14
  • 2021-06-10
  • 2021-09-07
  • 2021-08-07
  • 2021-05-17
相关资源
相似解决方案