Fortran多实例运行生成全局唯一临时文件名解决方案求助
可行解决方案如下:
方案1:调用系统mktemp命令生成唯一临时文件
系统原生的mktemp命令会自动保证生成的临时文件名全局唯一,不会出现同时间多实例重名问题,使用逻辑如下:
- 先生成唯一临时文件名,保存到中转文件中读取:
call execute_command_line('mktemp /tmp/find_res_XXXXXX > tmp_mktemp_name') ! 读取tmp_mktemp_name的内容得到唯一临时文件名 open(unit=10, file='tmp_mktemp_name', status='old') read(10, '(a)') tmp_name close(unit=10, status='delete')
- 再执行你的find命令写入该唯一临时文件:
call execute_command_line("find -ipath '*my_file' > " // trim(tmp_name))
- 读取完
tmp_name内容后及时删除该临时文件即可。
方案2:直接捕获命令输出,完全不使用临时文件
通过Fortran调用C标准库的popen函数直接读取find命令的输出流,从根源上避免临时文件冲突问题,参考实现代码:
use, intrinsic :: iso_c_binding implicit none ! 声明C库函数接口 interface function c_popen(cmd, mode) bind(C, name='popen') import :: c_ptr, c_char character(kind=c_char), intent(in) :: cmd(*), mode(*) type(c_ptr) :: c_popen end function function c_fgets(buf, n, stream) bind(C, name='fgets') import :: c_ptr, c_char, c_int character(kind=c_char), intent(out) :: buf(*) integer(c_int), value, intent(in) :: n type(c_ptr), value, intent(in) :: stream type(c_ptr) :: c_fgets end function function c_pclose(stream) bind(C, name='pclose') import :: c_ptr, c_int type(c_ptr), value, intent(in) :: stream integer(c_int) :: c_pclose end function function getpid() bind(C, name='getpid') import :: c_int integer(c_int) :: getpid end function end interface type(c_ptr) :: stream character(kind=c_char, len=2048) :: buf ! 要执行的find命令,末尾加C风格的空字符终止符 character(len=*), parameter :: find_cmd = "find -ipath '*my_file'"//c_null_char character(len=*), parameter :: read_mode = "r"//c_null_char ! 执行命令并获取输出流 stream = c_popen(find_cmd, read_mode) if (.not. c_associated(stream)) error stop "命令执行失败" ! 逐行读取匹配到的文件名 do if (.not. c_associated(c_fgets(buf, int(len(buf), c_int), stream))) exit ! 此处buf即为匹配到的文件名,直接处理即可,无需写入文件 print *, "匹配到文件:", trim(adjustl(buf)) end do ! 关闭流 call c_pclose(stream)
方案3:临时文件名加入进程ID保证唯一
每个运行的程序实例的进程ID(PID)是系统全局唯一的,将PID加入临时文件名即可完全避免重名,参考实现:
! 复用上面代码中的getpid接口声明 integer :: pid character(len=256) :: tmp_name pid = getpid() write(tmp_name, '(a, i0, a)') "tmp_find_res_", pid, ".txt" ! 后续执行find命令写入该tmp_name即可 call execute_command_line("find -ipath '*my_file' > " // trim(tmp_name))
如果程序内还用到了OpenMP多线程,可以再拼接omp_get_thread_num()的返回值,保证同进程内多线程也不会重名。
注意:所有使用临时文件的方案,处理完文件内容后都建议调用
execute_command_line('rm '//trim(tmp_name))删除临时文件,避免残留占用磁盘空间。
内容的提问来源于stack exchange,提问作者Mads M Pedersen
相关产品推荐
相关产品推荐

