如何保持与bc实例的跨进程管道连接持久化?
保持与bc实例的持久连接
当然可以实现持久化连接!你当前的问题在于每次调用open_session都会启动新的bc进程,没有复用已有的会话。我们可以通过存储进程的输入输出句柄来保持连接,直到主动关闭。以下是具体的实现方案:
核心思路
- 用动态谓词存储活跃的
bc会话信息(输入管道、输出管道、进程ID),确保整个程序运行期间复用同一个进程。 - 调整
open_session逻辑,优先复用已有会话,仅在无活跃会话时创建新进程。 - 实现主动关闭会话的谓词,清理资源并销毁会话状态。
完整代码实现
:- use_module(library(unix)). :- use_module(library(process)). :- use_module(library(readutil)). % 用于读取文本行 % 动态谓词:存储当前活跃的bc会话 :- dynamic current_bc_session/1. % 打开bc会话(复用已有会话,无则创建) open_session :- current_bc_session(_), !. % 已有会话,直接返回 open_session :- % 创建bc进程,建立管道连接 process_create( path(bc), [], [stdin(pipe(In)), stdout(pipe(Out)), process(Pid)] ), % 将会话信息存储到动态谓词中 assertz(current_bc_session(_{in: In, out: Out, pid: Pid})). % 读取bc的输出结果(bc返回文本行,用read_line_to_codes更合适) read_result(Out, Result) :- read_line_to_codes(Out, Codes), atom_codes(Result, Codes). % 向bc发送命令并获取结果(复用当前会话) send_command(Command, Result) :- current_bc_session(R), % 发送命令到bc的输入管道 write(R.in, Command), nl(R.in), flush_output(R.in), % 读取返回结果 read_result(R.out, Result). % 主动关闭bc会话,清理资源 close_bc_session :- current_bc_session(R), % 关闭输入输出管道 close(R.in), close(R.out), % 等待进程结束 process_wait(R.pid, _Status), % 移除会话状态 retractall(current_bc_session(_)).
关键细节说明
- 动态谓词
current_bc_session/1:这是持久化会话的核心,它会在内存中保存当前bc进程的所有连接信息,确保后续调用send_command时使用同一个进程。 - 会话复用逻辑:
open_session中的!(剪枝操作)确保如果已有活跃会话,不会执行后续的进程创建代码,直接复用已有会话。 - 输出读取优化:原代码中的
read/2是用于读取Prolog术语的,而bc返回的是普通文本行,所以改用read_line_to_codes/2读取并转换为原子,更符合实际需求。 - 异常处理(可选):如果担心
bc进程意外崩溃,可以在send_command中添加异常捕获,自动重建会话:send_command(Command, Result) :- current_bc_session(R), catch( (write(R.in, Command), nl(R.in), flush_output(R.in), read_result(R.out, Result)), error(io_error(_, _), _), (close_bc_session, open_session, send_command(Command, Result)) ).
使用示例
% 第一次调用会创建bc会话 ?- open_session, send_command("2+3", Res). Res = "5". % 后续调用复用同一个bc会话 ?- send_command("10*5", Res). Res = "50". % 主动关闭会话 ?- close_bc_session. true.
内容的提问来源于stack exchange,提问作者Anton Kochkov
相关产品推荐
相关产品推荐

