我正在用ncurses编写一个c ++多进程程序。
每个过程都需要在屏幕上显示内容。
我的示例代码:
unsigned int
但它只能在屏幕上显示一个进程的信息。
我该如何解决?
答案 0 :(得分:1)
该示例创建了两个4x4窗口,第二个偏移为8,8。所以他们没有共同的行。
由于你正在使用 fork (而不是 vfork ),这两个进程应该有单独的地址空间,并且一个进程应该没有办法刷新在其他进程中已修改的窗口。在某些情况下,开发人员选择将vfork
和fork
等同起来。使用Linux,vfork manual page comments:
标准说明
(来自POSIX.1)vfork()
功能与fork(2)
具有相同的效果, 除非行为 未定义 ,否则由vfork()
创建的流程 修改除pid_t
类型的变量以外的任何数据 存储来自vfork()
的返回值,或从函数中返回 在成功调用vfork()
或其中一个_exit(2)
之前调用exec(3)
,或调用任何其他函数强>功能家族。
但接着说
标准对
vfork()
的要求 弱 那些放在fork(2)
上的,所以这两者都是实现的 同义词 合规 。特别是程序员不能依赖 在父母被阻止之前,直到孩子终止或 调用 execve(2) ,并且不能依赖任何特定行为 尊重共享记忆。
弱和兼容是一个开发人员,他认为让这两个函数相似并不重要......
fork manual page断言有单独的地址空间:
子进程和父进程在 单独的内存中运行 空间 即可。在
fork()
时,两个内存空间都相同 内容。内存写入,文件映射(mmap(2)
)和取消映射 其中一个进程执行的(munmap(2)
)不会影响 其他
但我们在vfork
的描述中留下了这种模糊性。作为此vfork
行为的一部分,您的程序可能无法更新属于父进程的窗口 - 并且在建议的答案中刷新两个窗口仅确认fork
函数是伪装vfork
。
POSIX目前没有vfork
的页面。它有one here(fork
描述值得一读。)
无论哪种方式,使用vfork
实际上都不会改进。如果你必须在相同的地址空间内工作,那就是线程的用途。如果你必须使用单独的进程,让一个进程更新屏幕,其他进程与管道进行通信就是人们实际做的事情。
评论说,fork
已过时。 POSIX在这方面有不同的说法。引用posix_spawn
:
引入了posix_spawn()函数及其关系posix_spawnp()以克服fork()的以下感知困难:fork()函数在没有交换或动态地址转换的情况下很难或无法实现。
对于实时环境,交换通常太慢。
在POSIX可能有用的任何地方都无法使用动态地址转换。
只要必须在没有地址转换或其他MMU服务的情况下运行,进程就无法简单地选择POSIX。
因此,POSIX需要流程创建和文件执行原语,无需地址转换或其他MMU服务即可高效实现。
posix_spawn()函数可以作为库例程实现,但是posix_spawn()和posix_spawnp()都被设计为内核操作。此外,尽管它们可能是许多fork()/ exec对的有效替代品,但它们的目标是为fork(), 不提供插入式替换的系统提供有用的进程创建原语。 for fork()/ exec。
进一步阅读:
答案 1 :(得分:0)
我已经破解了一些丑陋的东西,大致有效但却显示出问题所在。我怀疑其他进程与之通信的单个窗口管理器进程会更好 - 或者是一些可怕的互斥体。
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
int main() {
initscr();
noecho();
curs_set(0);
WINDOW *win0 = newwin(4, 4, 0, 0);
WINDOW *win1 = newwin(4, 4, 8, 8);
int flag = fork();
if (flag == -1)
exit(1);
else if (flag == 0) {
int n = 0;
while (1) {
mvwprintw(win0, 0, 0, "%d", n % 9);
wrefresh(win0);
wrefresh(win1);
n = (n + 1) % 9;
sleep(1);
}
}
else {
int n = 0;
while (1) {
mvwprintw(win1, 0, 0, "%d", n % 9);
wrefresh(win1);
wrefresh(win0);
n = (n + 1) % 9;
sleep(1);
}
}
endwin();
return 0;
}