如果您想了解读取器closures命名pipe道和FIFO时检测的知识,那么本篇文章将是您的不二之选。我们将深入剖析读取器closures命名pipe道的各个方面,并为您解答FIFO时检测的疑在这篇文
如果您想了解读取器closures命名pipe道和FIFO时检测的知识,那么本篇文章将是您的不二之选。我们将深入剖析读取器closures命名pipe道的各个方面,并为您解答FIFO时检测的疑在这篇文章中,我们将为您介绍读取器closures命名pipe道的相关知识,同时也会详细的解释FIFO时检测的运用方法,并给出实际的案例分析,希望能帮助到您!
本文目录一览:- 读取器closures命名pipe道(FIFO)时检测(读取器是什么)
- linux – 检测读取器何时关闭命名管道(FIFO)
- Linux 进程间通信 有名管道(fifo)
- linux系统中的有名管道(FIFO)
- logging到非阻塞的命名pipe道?
读取器closures命名pipe道(FIFO)时检测(读取器是什么)
我需要知道这一点,因为我写入pipe道的初始数据是不同的; 在数据的其他部分出现之前,读者正在等待一个初始标题。
目前,当我的write()与EPIPE失败时,我检测到这一点。 然后我设置一个标志,说“下一次,发送标题”。 但是,在我写任何东西之前,读者可以closures并重新打开pipe道。 在这种情况下,我从来没有意识到他做了什么,也不会发送他期待的头球。
有没有什么asynchronous事件types的东西可以帮助这里? 我没有看到任何信号被发送。
Bash到批量转换
os.fork()会在写入时使用copy还是在Python中完成父进程的完整副本?
Bash数组创build:(“$ @”)vs($ @)
在terminal窗口中启动文件pipe理器
使用相同的密钥循环访问关联数组
请注意,我没有包含任何语言标记,因为这个问题应该被认为是语言不可知的。我的代码是Python,但答案应该适用于C或其他具有系统调用级别绑定的语言。
在bdist_rpm中设置RPM包名称
为什么“猫a.txt | xargs vi“销毁bash?
Windows / Linux的iOS应用程序开发(编译不需要)
我怎样才能创build一个基于.png文件的像素图?
GCC 4.7源字符编码和执行字符编码string文字?
如果您正在使用基于poll系统调用的事件循环,则可以使用包含EPOLLERR的事件掩码来注册管道。 在Python中, select.poll ,
import select fd = open("pipe","w") poller = select.poll() poller.register(fd,select.POLLERR) poller.poll()
将等待,直到管道关闭。
要测试这个,运行mkfifo pipe ,启动脚本,并在另一个终端运行,例如cat pipe 。 一旦你退出cat进程,脚本将会终止。
奇怪的是,当最后一个阅读器关闭管道时, select显示管道是可读的:
writer.py
#!/usr/bin/env python import os import select import time NAME = 'fifo2' os.mkfifo(NAME) def select_test(fd,r=True,w=True,x=True): rset = [fd] if r else [] wset = [fd] if w else [] xset = [fd] if x else [] t0 = time.time() r,w,x = select.select(rset,wset,xset) print 'After {0} sec:'.format(time.time() - t0) if fd in r: print ' {0} is readable'.format(fd) if fd in w: print ' {0} is writable'.format(fd) if fd in x: print ' {0} is exceptional'.format(fd) try: fd = os.open(NAME,os.O_WRONLY) print '{0} opened for writing'.format(NAME) print 'select 1' select_test(fd) os.write(fd,'test') print 'wrote data' print 'select 2' select_test(fd) print 'select 3 (no write)' select_test(fd,w=False) finally: os.unlink(NAME)
演示:
1号航站楼:
$ ./pipe_example_simple.py fifo2 opened for writing select 1 After 1.59740447998e-05 sec: 3 is writable wrote data select 2 After 2.86102294922e-06 sec: 3 is writable select 3 (no write) After 2.15910816193 sec: 3 is readable
2号航站楼:
$ cat fifo2 test # (wait a sec,then Ctrl+C)
没有这样的机制。 一般情况下,根据UNIX方式,任何一端都没有流打开或关闭的信号。 这只能通过阅读或写入来检测(相应地)。
我会说这是错误的设计。 目前,您正尝试让接收机通过打开管道来显示其可用性。 所以要么以适当的方式实现这个信号,要么在管道的发送部分中包含“关闭逻辑”。
linux – 检测读取器何时关闭命名管道(FIFO)
解决方法
import select fd = open("pipe","w") poller = select.poll() poller.register(fd,select.POLLERR) poller.poll()@H_301_2@将等到管道关闭. @H_301_2@要对此进行测试,请运行mkfifo pipe,启动脚本,然后在另一个终端运行中运行,例如cat pipe.一旦退出cat进程,脚本将终止.
Linux 进程间通信 有名管道(fifo)
有名管道特点:
1)无名管道只能用于具有亲缘关系的进程之间,这就限制了无名管道的使用范围
2)有名管道可以使互不相关的两个进程互相通信。
3)有名管道可以通过路径名来指出,并且在文件系统中可见,但内容存放在内存中。
4)进程通过文件 IO 来操作有名管道
5)有名管道遵循先进先出规则
6)不支持如 lseek () 操作
注意:
以 O_WRONLY 打开管道,读阻塞
以 O_RDWR 打开管道,当管道中没有数据,读阻塞
// 当进程用 open 打开有名管道用只读方式打开的话,则返回的文件描述符就代表管道的读端
创建有名管道:
int mkfifo(const char *filename, mode_t mode)
参数:filename 有名管道文件名(包括路径);mode 权限(读写 0666)
成功返回 0 ,失败返回 - 1 并设置 errno 号 errno == EEXIST 时表示该有名管道已经存在
对有名管道的操作是通过文件 IO 中的 open read write 等操作的
例子:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, const char *argv[])
{
char buf[50] = {0};
if(mkfifo("./fifo",0777) != 0 ) //在当前路径下(运行程序所在的路径)创建有名管道,有名管道权限读写执行
{
if(errno == EEXIST) //当该有名管道存在时,提示下
{
printf("File exists\n");
}
else
{
perror("mkfifo fail ");
exit(1);
}
}
int fd;
fd = open("./fifo",O_RDWR);//读写方式打开,使用文件IO 操作有名管道
if(fd < 0)
{
perror("open fifo fail: ");
exit(1);
}
write(fd,"1234567",7);
read(fd,buf,7);
printf("%s\n",buf);
return 0;
}
测试:
例子:通过有名管道让两个进程实现文件的复制
(1)读取文件写入有名管道中
/* 功能:实现在终端上输入获取文件名,读取文件内容,写到有名管道fifo中
* */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, const char *argv[])
{
char buf[50] = {0};
if(mkfifo("./fifo",0777) != 0 ) //创建有名管道
{
if(errno == EEXIST)
{
printf("File exists\n");
}
else
{
perror("mkfifo fail ");
exit(1);
}
}
int fd_fifo,fd_file;
fd_fifo = open("./fifo",O_WRONLY);//只写方式打开,管道描述符
if(fd_fifo < 0)
{
perror("open fifo fail: ");
exit(1);
}
fd_file = open(argv[1],O_RDONLY);//只读方式打开,源文件进行复制到管道中
if(fd_file < 0)
{
perror("open source fail ");
exit(1);
}
//循环读取文件内容
ssize_t size;
while(1)
{
size = read(fd_file,buf,50); //文件中读取数据,返回读取到多少数据
if(size <= 0)
{
break;
}
write(fd_fifo,buf,size);
}
close(fd_file);//关闭读的源文件
close(fd_fifo);
return 0;
}
(2)读取有名管道中的数据,写入文件中实现复制
/* 功能:实现在有名管道中读取数据,写到文件中
* */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, const char *argv[])
{
char buf[50] = {0};
if(mkfifo("./fifo",0777) != 0 ) //创建有名管道
{
if(errno == EEXIST) //有名管道存在的情况
{
printf("File exists\n");
}
else
{
perror("mkfifo fail ");
exit(1);
}
}
int fd_fifo,fd_file; //此处fd_r是指有名管道,在有名管道中读取数据,写到文件中
fd_fifo = open("./fifo",O_RDONLY);//读方式打开
if(fd_fifo < 0)
{
perror("open fifo fail: ");
exit(1);
}
fd_file = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666);//把从有名管道中读取的数据,写到文件中,只读,没有创建,清空打开
if(fd_file < 0)
{
perror("fd_w open fail ");
exit(1);
}
//fifo 中循环读取数据,然后写到文件中
ssize_t size;
while(1)
{
size = read(fd_fifo,buf,50); //读有名管道内容,返回读取多少个数据
if(size <= 0)
{
break;
}
write(fd_file,buf,size); //写入文件中
}
close(fd_fifo);
close(fd_file);
return 0;
}
测试:此时要打开两个终端让两个进程进行通信,一个执行写操作,一个执行都操作(有名管道中有数据才可以读,且管道数据内容存在内存中)
linux系统中的有名管道(FIFO)
无名管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(named pipe或FIFO)提出后,该限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,通过FIFO不相关的进程也能交换数据。值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。
管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小)
管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等
FIFO往往都是多个写进程,一个读进程。
FIFO的打开规则:
- 如果当前打开操作是为读而打开FIFO时,若已经有相应进程为写而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置了阻塞标志);或者,成功返回(当前打开操作没有设置阻塞标志)。
- 如果当前打开操作是为写而打开FIFO时,如果已经有相应进程为读而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作设置了阻塞标志);或者,返回ENXIO错误(当前打开操作没有设置阻塞标志)。
总之就是一句话,一旦设置了阻塞标志,调用mkfifo建立好之后,那么管道的两端读写必须分别打开,有任何一方未打开,则在调用open的时候就阻塞。
从FIFO中读取数据:
约定:如果一个进程为了从FIFO中读取数据而阻塞打开FIFO,那么称该进程内的读操作为设置了阻塞标志的读操作。(意思就是我现在要打开一个有名管道来读数据!)
如果有进程写打开FIFO,且当前FIFO内没有数据(可以理解为管道的两端都建立好了,但是写端还没开始写数据!)
- 则对于设置了阻塞标志的读操作来说,将一直阻塞(就是block住了,等待数据。它并不消耗CPU资源,这种进程的同步方式对CPU而言是非常有效率的。)
- 对于没有设置阻塞标志读操作来说则返回-1,当前errno值为EAGAIN,提醒以后再试。
对于设置了阻塞标志的读操作说(见上面的约定)
造成阻塞的原因有两种
- FIFO内有数据,但有其它进程在读这些数据
- FIFO内没有数据。解阻塞的原因则是FIFO中有新的数据写入,不论信写入数据量的大小,也不论读操作请求多少数据量。
读打开的阻塞标志只对本进程第一个读操作施加作用,如果本进程内有多个读操作序列,则在第一个读操作被唤醒并完成读操作后,其它将要执行的读操作将不再阻塞,即使在执行读操作时,FIFO中没有数据也一样,此时,读操作返回0。
注:如果FIFO中有数据,则设置了阻塞标志的读操作不会因为FIFO中的字节数小于请求读的字节数而阻塞,此时,读操作会返回FIFO中现有的数据量。
向FIFO中写入数据:
约定:如果一个进程为了向FIFO中写入数据而阻塞打开FIFO,那么称该进程内的写操作为设置了阻塞标志的写操作。
对于设置了阻塞标志的写操作:
- 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果此时管道空闲缓冲区不足以容纳要写入的字节数,则进入睡眠,直到当缓冲区中能够容纳要写入的字节数时,才开始进行一次性写操作。(PIPE_BUF ==>> /usr/include/linux/limits.h)
- 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。FIFO缓冲区一有空闲区域,写进程就会试图向管道写入数据,写操作在写完所有请求写的数据后返回。
对于没有设置阻塞标志的写操作:
- 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。在写满所有FIFO空闲缓冲区后,写操作返回。
- 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果当前FIFO空闲缓冲区能够容纳请求写入的字节数,写完后成功返回;如果当前FIFO空闲缓冲区不能够容纳请求写入的字节数,则返回EAGAIN错误,提醒以后再写;
简单描述下上面设置了阻塞标志的逻辑
设置了阻塞标志
if (buf_to_write then if ( buf_to_write > system_buf_left ) //保证写入的原子性,要么一次性把buf_to_write全都写完,要么一个字节都不写! then block ; until ( buf_to_write else write ; fi else write ; //不管怎样,就是不断写,知道把缓冲区写满了才阻塞 fi
管道写端 pipe_read.c
/pipe_read.c #include #include #include #include #include #include #include #define FIFO_NAME "/tmp/my_fifo" #define BUFFER_SIZE PIPE_BUF int main() { int pipe_fd; int res; int open_mode = O_RDONLY; char buffer[BUFFER_SIZE + 1]; int bytes = 0; memset(buffer, ''\0'', sizeof(buffer)); printf("Process %d opeining FIFO O_RDONLY\n", getpid()); pipe_fd = open(FIFO_NAME, open_mode); printf("Process %d result %d\n", getpid(), pipe_fd); if (pipe_fd != -1) { do{ res = read(pipe_fd, buffer, BUFFER_SIZE); bytes += res; printf("%d\n",bytes); }while(res > 0); close(pipe_fd); } else { exit(EXIT_FAILURE); } printf("Process %d finished, %d bytes read\n", getpid(), bytes); exit(EXIT_SUCCESS); }
管道读端 pipe_write.c
//pipe_write.c #include #include #include #include #include #include #include #define FIFO_NAME "/tmp/my_fifo" #define BUFFER_SIZE PIPE_BUF #define TEN_MEG (1024 * 100) int main() { int pipe_fd; int res; int open_mode = O_WRONLY; int bytes = 0; char buffer[BUFFER_SIZE + 1]; if (access(FIFO_NAME, F_OK) == -1) { res = mkfifo(FIFO_NAME, 0777); if (res != 0) { fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME); exit(EXIT_FAILURE); } } printf("Process %d opening FIFO O_WRONLY\n", getpid()); pipe_fd = open(FIFO_NAME, open_mode); printf("Process %d result %d\n", getpid(), pipe_fd); //sleep(20); if (pipe_fd != -1) { while (bytes if (res == -1) { fprintf(stderr, "Write error on pipe\n"); exit(EXIT_FAILURE); } bytes += res; printf("%d\n",bytes); } close(pipe_fd); } else { exit(EXIT_FAILURE); } printf("Process %d finish\n", getpid()); exit(EXIT_SUCCESS); }
本文介绍了linux系统中的有名管道(FIFO)的方法,包括有名管道的创建、打开、读写、关闭和删除等方面。通过了解和掌握这些知识,我们可以更好地使用有名管道(FIFO)来实现进程间通信,提高系统的性能和可靠性。当然,linux系统中的有名管道(FIFO)还有很多其他的特性和用法,需要我们不断地学习和探索。希望本文能给你带来一些启发和帮助。
以上就是
logging到非阻塞的命名pipe道?
我有一个问题,我不能在任何地方find帮助或帮助。
我有一个程序(芹菜分布式任务队列),我有多个实例(工人)每个有一个日志文件(celery_worker1.log,celery_worker2.log)。
重要的错误被存储到数据库中,但是我喜欢在运行新操作时不时确定这些日志,以确保一切正常(日志级别较低)。
我的问题:这些日志正在占用大量的磁盘空间。 我想做的事情是:只有在需要的时候才能“看”日志(tail -f),而不用占用大量的空间。
.NET跟踪日志查看器
javaparsing日志文件
在Nginx中logging代理活动
在大文件上格式化多个string
使用三通(或同等)但限制最大文件大小或旋转到新文件
我的想法直到现在:
输出日志到标准输出,而不是一个文件:不可能在这里,因为我有很多工人输出到不同的文件,但我想一次拖尾(tail -f celery_worker * .log)
使用logrotate:这对我来说是一个“OK”的解决scheme。 我不希望这是一个日常的任务,而不是把一分钟的crontab这个,更多的是,服务器不是我的,所以这将意味着一些工作在pipe理系统端
使用命名pipe道:它看起来一见钟情,但我不知道命名pipe道(Linux FIFO)在哪里阻塞。 因此,当我没有同时尾随所有的pipe道,或者当我刚刚离开我的尾巴时,logging器的写入操作被阻止。
有没有办法有一个非阻塞的命名pipe道,只是抛出时,标准输出,并抛出/ dev / null时不?
或者这种pipe道有技术上的困难吗? 如果有,他们是什么?
谢谢您的回答!
PHP日志文件的颜色
如何在Linux上loggingcpu,内存和带宽?
在Windows程序中打印debugging输出
数据结构来存储数十亿整数
C ++ / W32 – 录制声音,直接显示或WaveInopen?
让每个工作人员登录到stdout,但将每个stdout连接到一个实用程序,该实用程序根据大小或时间自动后台打印和旋转日志。 multilog和svlogd就是这样的例子。 对于那些程序,你只需要尾随“当前”日志文件。
你说得对,logrotate不是你所遇到的问题的正确解决方案。
命名管道将无法正常工作。 充其量,你的作家可以填满他们的管道,然后丢弃随后的日志,这是你想要的行为的反面。
你可以尝试共享内存设备man:shm_overview或者其中的一些。 您需要将它们组织为循环缓冲区,以便它们能够存储您的日志的最后N个字节,并且每当您用读取器读取它时,它都会将所有内容输出到您的控制台。 这种方法被busyBox的syslog / logread套装(见logread.c )所采用。
总结
以上是小编为你收集整理的logging到非阻塞的命名pipe道?全部内容。
如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。
今天关于读取器closures命名pipe道和FIFO时检测的分享就到这里,希望大家有所收获,若想了解更多关于linux – 检测读取器何时关闭命名管道(FIFO)、Linux 进程间通信 有名管道(fifo)、linux系统中的有名管道(FIFO)、logging到非阻塞的命名pipe道?等相关知识,可以在本站进行查询。
本文标签: