GVKun编程网logo

读取器closures命名pipe道(FIFO)时检测(读取器是什么)

13

如果您想了解读取器closures命名pipe道和FIFO时检测的知识,那么本篇文章将是您的不二之选。我们将深入剖析读取器closures命名pipe道的各个方面,并为您解答FIFO时检测的疑在这篇文

如果您想了解读取器closures命名pipe道FIFO时检测的知识,那么本篇文章将是您的不二之选。我们将深入剖析读取器closures命名pipe道的各个方面,并为您解答FIFO时检测的疑在这篇文章中,我们将为您介绍读取器closures命名pipe道的相关知识,同时也会详细的解释FIFO时检测的运用方法,并给出实际的案例分析,希望能帮助到您!

本文目录一览:

读取器closures命名pipe道(FIFO)时检测(读取器是什么)

读取器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)

linux – 检测读取器何时关闭命名管道(FIFO)

有没有办法让作者知道读者已经关闭了命名管道(或退出)的末尾而没有写入它? @H_301_2@我需要知道这一点,因为我写入管道的初始数据是不同的;读者期望在其余数据到来之前有一个初始标题.

@H_301_2@目前,当我的write()因EPIPE失败时,我会检测到这一点.然后我设置了一个标志,上面写着“下次发送标题”.但是,在我写任何东西之前,读者可以关闭并重新打开管道.在这种情况下,我从来没有意识到他做了什么,也没有发送他期待的标题.

@H_301_2@是否存在任何类型的异步事件类型可能对此有所帮助?我没有看到任何信号被发送.

@H_301_2@请注意,我没有包含任何语言标记,因为这个问题应该被视为与语言无关.我的代码是Python,但答案应该适用于C或任何其他具有系统调用级绑定的语言.

解决方法

如果您使用的是基于轮询系统调用的事件循环,则可以使用包含EPOLLERR的事件掩码注册管道.在Python中,使用select.poll,
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)

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)

linux系统中的有名管道(FIFO)

linux系统是一种支持多任务并发执行的操作系统,它可以同时运行多个进程,从而提高系统的利用率和效率。但是,如果这些进程之间需要进行数据交换和协作,就需要使用一些进程间通信(ipc)的方式,例如信号、消息队列、共享内存、信号量等。其中,有名管道(fifo)是一种比较简单而强大的ipc方式,它可以让两个或多个进程通过一个文件来进行数据传输,无需关心文件的内容和格式。本文将介绍linux系统中的有名管道(fifo)的方法,包括有名管道的创建、打开、读写、关闭和删除等方面。

linux系统中的有名管道(FIFO)

无名管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(named pipe或FIFO)提出后,该限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,通过FIFO不相关的进程也能交换数据。值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。
管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小)
管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等

FIFO往往都是多个写进程,一个读进程。

FIFO的打开规则:

  1. 如果当前打开操作是为读而打开FIFO时,若已经有相应进程为写而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置了阻塞标志);或者,成功返回(当前打开操作没有设置阻塞标志)。
  2. 如果当前打开操作是为写而打开FIFO时,如果已经有相应进程为读而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作设置了阻塞标志);或者,返回ENXIO错误(当前打开操作没有设置阻塞标志)。

总之就是一句话,一旦设置了阻塞标志,调用mkfifo建立好之后,那么管道的两端读写必须分别打开,有任何一方未打开,则在调用open的时候就阻塞。

从FIFO中读取数据:

约定:如果一个进程为了从FIFO中读取数据而阻塞打开FIFO,那么称该进程内的读操作为设置了阻塞标志的读操作。(意思就是我现在要打开一个有名管道来读数据!)

如果有进程写打开FIFO,且当前FIFO内没有数据(可以理解为管道的两端都建立好了,但是写端还没开始写数据!)

  1. 则对于设置了阻塞标志的读操作来说,将一直阻塞(就是block住了,等待数据。它并不消耗CPU资源,这种进程的同步方式对CPU而言是非常有效率的。)
  2. 对于没有设置阻塞标志读操作来说则返回-1,当前errno值为EAGAIN,提醒以后再试。

对于设置了阻塞标志的读操作说(见上面的约定)
造成阻塞的原因有两种

  1. FIFO内有数据,但有其它进程在读这些数据
  2. FIFO内没有数据。解阻塞的原因则是FIFO中有新的数据写入,不论信写入数据量的大小,也不论读操作请求多少数据量。

读打开的阻塞标志只对本进程第一个读操作施加作用,如果本进程内有多个读操作序列,则在第一个读操作被唤醒并完成读操作后,其它将要执行的读操作将不再阻塞,即使在执行读操作时,FIFO中没有数据也一样,此时,读操作返回0。

注:如果FIFO中有数据,则设置了阻塞标志的读操作不会因为FIFO中的字节数小于请求读的字节数而阻塞,此时,读操作会返回FIFO中现有的数据量。

向FIFO中写入数据:

约定:如果一个进程为了向FIFO中写入数据而阻塞打开FIFO,那么称该进程内的写操作为设置了阻塞标志的写操作。

对于设置了阻塞标志的写操作:

  1. 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果此时管道空闲缓冲区不足以容纳要写入的字节数,则进入睡眠,直到当缓冲区中能够容纳要写入的字节数时,才开始进行一次性写操作。(PIPE_BUF ==>> /usr/include/linux/limits.h)
  2. 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。FIFO缓冲区一有空闲区域,写进程就会试图向管道写入数据,写操作在写完所有请求写的数据后返回。

对于没有设置阻塞标志的写操作:

  1. 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。在写满所有FIFO空闲缓冲区后,写操作返回。
  2. 当要写入的数据量不大于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)还有很多其他的特性和用法,需要我们不断地学习和探索。希望本文能给你带来一些启发和帮助。

以上就是linux系统中的有名管道(FIFO)的详细内容,更多请关注php中文网其它相关文章!

logging到非阻塞的命名pipe道?

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道?等相关知识,可以在本站进行查询。

本文标签: