Куда попадают данные именованного канала (FIFO) при отключении считывателя?

Допустим, у меня есть producer.go и consumer.go. consumer.go читает из именованного канала UNIX, а производитель записывает в именованный канал.

Как и ожидалось, если вы запустите только одну программу-производителя или программу-потребитель, она зависнет, потому что на другой стороне конвейера нет ни чтения, ни записи.

Теперь, если я запускаю обе программы, то сразу же CTRL-C от потребителя, производитель продолжает отправлять данные в канал, и, насколько я могу судить, нет ограничений на размер этих данных (я отправил 80 МБ)

Если я снова запускаю программу-потребитель (пока производитель все еще работает), она начинает извлекать данные из именованного канала, но не данные, которые я «пропустил», пока программа-потребитель не работала.

Мой вопрос: Когда устройство чтения именованного канала отключается, что происходит с данными, отправленными в именованный канал?

Вот мои программы consumer.go и producer.go:

потребитель.go

package main

import (
    "io"
    "io/ioutil"
    "log"
    "os"
    "syscall"
)

func main() {
    syscall.Mkfifo("fifo0", 0777)
    fp, err := os.OpenFile("fifo0", os.O_RDONLY, 0777)
    if err != nil {
        log.Fatalf("Could not open fifo0: %s", err)
    }
    tee := io.TeeReader(fp, os.Stdout)
    ioutil.ReadAll(tee)
}

продюсер.го

package main

import (
    "fmt"
    "io"
    "log"
    "os"
    "strings"
    "time"
)

func main() {
    dots := strings.Repeat(".", 990)
    fifo, err := os.OpenFile("fifo0", os.O_WRONLY, 0777)
    if err != nil {
        log.Fatalf("Could not open fifo0: %s", err)
    }
    defer fifo.Close()
    w := io.MultiWriter(os.Stdout, fifo)
    for i := 0; i < 8000; i++ {
        fmt.Fprintf(w, "%010d%s\n", i, dots)
        time.Sleep(time.Millisecond * 10)
    }
}

person Scott Frazer    schedule 06.08.2016    source источник
comment
Вы не проверяете ошибки при записи в канал   -  person JimB    schedule 06.08.2016
comment
Когда я проверяю наличие ошибок, оказывается, что он показывает ошибку, когда приемника нет, но он не блокируется, это приятно знать.   -  person Scott Frazer    schedule 06.08.2016


Ответы (1)


Для FIFO требуется как минимум один источник и одно место назначения для передачи данных куда угодно. Только читатель ждет, чтобы получить от кого-то, и только писатель ждет, чтобы послать кому-то. Таким образом, в трубе один к одному не остается зазоров.

Поэтому, если вы все еще пытаетесь читать или писать с одного конца отключенного или несуществующего канала, ответ таков: данные никуда не денутся; канал «заблокирован» и не может содержать собственных данных. Так что это зависит от того, как ваш код обрабатывает эту ситуацию.

В producer.go цикл продолжает работать, даже если соединение больше не существует. Потому что Fprintf или MultiWriter ни по какой причине не вызывают ошибку остановки кода. В этом случае можно либо добавить проверку в цикле, либо обработчик события на отключение объекта fifo.

Причина, по которой кажется, что существует пробел в исчезающих данных, заключается в том, что цикл продолжает повторяться для i и генерирует строки, которые он не может отправить.

person Beejor    schedule 14.04.2019