/ / Напишете повече от 4K байта в exec.Cmd.StdinPipe () - отидете, обработвайте, тръба, ipc

Напишете повече от 4K байта на exec.Cmd.StdinPipe () - go, process, pipe, ipc

проблем

Когато пишете данни над 4096 байта до Cmd.StdinPipe в Go, обработката на програмата спира на Windows. Това явление не се появява, когато един и същ код работи на Linux или когато пишете процес, използвайки goroutine.

въпрос

Обработката няма да продължи _, err = in.Write ([] byte {"0"}) (4097 байта) в кода, показан по-долу. Защо е това?

Защо не се случва с goroutine или в Linux?

*** Препратката към Golang описва Cmd.StdinPipe, използвайки goroutine като пример, и проблемът ми също е решен. Този въпрос възниква от любопитството към Go.

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

Отговори:

7 за отговор № 1

Писане само на блокове, ако в тръбата няма повече място. Въпреки че размерът на тръбата в Windows може да бъде 4k, той е много по-голям в Linux. от тръба (7):

... От Linux 2.6.11, капацитетът на тръбата е 16 страници (т.е. 65,536 байта в система с размер на страницата 4096 байта) ...

По този начин вероятно ще получите същия резултат в Linux, както и в Windows, когато пишете в тръба, където никой не чете, но трябва да запишете много повече данни в тръбата, докато стигнете до тази ситуация.


0 за отговор № 2

На това вече е отговорено, ето това вероятно ще искате да използвате, ако се сблъскате с този проблем - използвайте вместо това буферирания писател, наличен в bufio пакет. Това ви позволява да обгърнете писател с по-голям буфер, над който имате пълен контрол.