Записать больше 4K байтов в exec.Cmd.StdinPipe () - PullRequest
0 голосов
/ 01 мая 2018

Задача

При записи данных, превышающих 4096 байт, в Cmd.StdinPipe в Go обработка программы останавливается в Windows. Это явление не возникает, когда тот же код выполняется в Linux или при написании процесса с использованием goroutine.

Вопрос

Обработка не будет начинаться с _, err = in.Write ([] byte {'0'}) (4097 байт) в коде, показанном ниже. Почему это?

Почему это не происходит с goroutine или в Linux?

*** Ссылка на Голанг описывает Cmd.StdinPipe с использованием goroutine как пример , и моя проблема также была решена. Этот вопрос возникает из любопытства о Го.

package main

import (
    "bytes"
    "fmt"
    "io"
    "log"
    "os/exec"
)

func main() {
    cmd := exec.Command("more")

    pype, err := cmd.StdinPipe()
    if err != nil {
        log.Fatal(err)
    }

    bytes4k := generateBytes(1024 * 4) // Works on Linux, but not Windows.
    // bytes4k := generateBytes(1024 * 64) // Don't works on Linux and Windows.
    fmt.Println("bytes generated.")

    // go writeBytes(pype, bytes4k) // Works fine!
    writeBytes(pype, bytes4k) // Can't write. Write is locked.

    err = cmd.Run()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("finished.")
}

func generateBytes(num int) []byte {
    byte := bytes.NewBuffer(make([]byte, 0, num))
    for i := 0; i < num; i++ {
        byte.WriteByte('0')
    }
    return byte.Bytes()
}

func writeBytes(in io.WriteCloser, bytes []byte) {
    defer in.Close()

    _, err := in.Write(bytes)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("written bytes to pipe.")

    _, err = in.Write([]byte{'0'}) // Why this code stops at 4097 bytes?
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("written 1 byte to pipe.")
}

Проверенные версии

  • go версия go1.10.1 windows / amd64
  • go версия go1.10.1 linux / amd64

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

На этот вопрос уже получен ответ, вот обходной путь, который вы, вероятно, захотите использовать, если столкнетесь с этой проблемой - используйте вместо этого буферизованный модуль записи, доступный в пакете bufio . Это позволяет вам обернуть писатель большим буфером, который вы можете полностью контролировать.

0 голосов
/ 01 мая 2018

Запись только блоков, если в трубе больше нет места. Хотя размер канала в Windows может быть 4 КБ, в Linux он намного больше. Из трубы (7) :

... начиная с Linux 2.6.11, объем канала составляет 16 страниц (т. Е. 65 536 байт в системе с размером страницы 4096 байт) ...

Таким образом, вы, вероятно, получите тот же результат в Linux, что и в Windows, при записи в канал, где никто не читает, но вам нужно записать в канал больше данных, пока вы не достигнете этой ситуации.

...