Anda tahu, saya tidak yakin Anda tentu membutuhkan umpan balik berulang-ulang sebagai diagram Anda menggambarkan, begitu banyak seperti mungkin Anda bisa menggunakan persisten pipa antara coprocesses . Kemudian lagi, mungkin tidak ada terlalu banyak perbedaan - setelah Anda membuka garis pada suatu proses, Anda dapat menerapkan loop gaya khas hanya dengan menulis informasi dan membaca informasi darinya tanpa melakukan sesuatu yang sangat luar biasa.
Pertama-tama, akan terlihat bahwa itu bc
adalah kandidat utama untuk proses-ulang untuk Anda. Di bc
Anda dapat define
fungsi yang dapat melakukan cukup banyak apa yang Anda minta di pseudocode Anda. Misalnya, beberapa fungsi yang sangat sederhana untuk melakukan ini dapat terlihat seperti:
printf '%s()\n' b c a |
3<&0 <&- bc -l <<\IN <&3
a=1; b=0; c=0;
define a(){ "a="; return (a = c+1); }
define b(){ "b="; return (b = 3*a); }
define c(){ "c="; return (c = s(b)); }
IN
... yang akan mencetak ...
b=3
c=.14112000805986722210
a=1.14112000805986722210
Tapi tentu saja, itu tidak bertahan lama . Segera setelah subkulit yang bertanggung jawab atas printf
pipa berhenti (tepat setelah printf
menulis a()\n
ke pipa) pipa tersebut dirobohkan dan bc
input menutup dan juga berhenti. Itu hampir tidak berguna seperti yang seharusnya.
@derobert telah menyebutkan FIFO s seperti yang bisa didapat dengan membuat file pipa bernama dengan mkfifo
utilitas. Ini pada dasarnya hanya pipa juga, kecuali kernel sistem menautkan entri sistem file ke kedua ujungnya. Ini sangat berguna, tetapi akan lebih baik jika Anda hanya dapat memiliki pipa tanpa risiko mengintai di sistem file.
Ketika itu terjadi, shell Anda sering melakukan ini. Jika Anda menggunakan shell yang menerapkan substitusi proses maka Anda memiliki cara yang sangat mudah untuk mendapatkan pipa yang tahan lama - dari jenis yang mungkin Anda tetapkan untuk proses latar belakang yang dengannya Anda dapat berkomunikasi.
Dalam bash
, misalnya, Anda dapat melihat cara kerja proses substitusi:
bash -cx ': <(:)'
+ : /dev/fd/63
Anda lihat itu benar-benar substitusi . Shell mengganti nilai selama ekspansi yang sesuai dengan jalur ke tautan ke pipa . Anda dapat memanfaatkan itu - Anda tidak perlu dibatasi untuk menggunakan pipa itu hanya untuk berkomunikasi dengan proses apa pun yang berjalan di dalam ()
substitusi itu sendiri ...
bash -c '
eval "exec 3<>"<(:) "4<>"<(:)
cat <&4 >&3 &
echo hey cat >&4
read hiback <&3
echo "$hiback" here'
... yang mencetak ...
hey cat here
Sekarang saya tahu bahwa shell yang berbeda melakukan hal coprocess dengan cara yang berbeda - dan bahwa ada sintaks khusus bash
untuk pengaturan satu (dan mungkin satu untuk zsh
juga) - tetapi saya tidak tahu bagaimana hal-hal itu bekerja. Saya hanya tahu bahwa Anda dapat menggunakan sintaks di atas untuk melakukan hal yang hampir sama tanpa semua omong kosong di keduanya bash
dan zsh
- dan Anda dapat melakukan hal yang sangat mirip dash
dan busybox ash
untuk mencapai tujuan yang sama dengan dokumen-dokumen di sini (karena dash
dan busybox
lakukan di sini- dokumen dengan pipa daripada file temp seperti yang dilakukan dua lainnya) .
Jadi, ketika diterapkan ke bc
...
eval "exec 3<>"<(:) "4<>"<(:)
bc -l <<\INIT <&4 >&3 &
a=1; b=0; c=0;
define a(){ "a="; return (a = c+1); }
define b(){ "b="; return (b = 3*a); }
define c(){ "c="; return (c = s(b)); }
INIT
export BCOUT=3 BCIN=4 BCPID="$!"
... itu bagian yang sulit. Dan ini adalah bagian yang menyenangkan ...
set --
until [ "$#" -eq 10 ]
do printf '%s()\n' b c a >&"$BCIN"
set "$@" "$(head -n 3 <&"$BCOUT")"
done; printf %s\\n "$@"
... yang mencetak ...
b=3
c=.14112000805986722210
a=1.14112000805986722210
#...24 more lines...
b=3.92307618030433853649
c=-.70433330413228041035
a=.29566669586771958965
... dan masih berjalan ...
echo a >&"$BCIN"
read a <&"$BCOUT"
echo "$a"
... yang hanya membuat saya nilai terakhir untuk bc
's a
daripada memanggil a()
fungsi untuk kenaikan itu dan cetakan ...
.29566669586771958965
Ini akan terus berjalan, pada kenyataannya, sampai saya membunuhnya dan menghancurkan pipa IPC-nya ...
kill "$BCPID"; exec 3>&- 4>&-
unset BCPID BCIN BCOUT