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 bcadalah kandidat utama untuk proses-ulang untuk Anda. Di bcAnda dapat definefungsi 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 printfpipa berhenti (tepat setelah printfmenulis a()\nke pipa) pipa tersebut dirobohkan dan bcinput 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 mkfifoutilitas. 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 bashuntuk pengaturan satu (dan mungkin satu untuk zshjuga) - 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 bashdan zsh- dan Anda dapat melakukan hal yang sangat mirip dashdan busybox ashuntuk mencapai tujuan yang sama dengan dokumen-dokumen di sini (karena dashdan busyboxlakukan 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 adaripada 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