我正在尝试教dwm在每个标签(www,文件,音乐...)中打开适当的应用程序。 dwm.c中有一个名为view
的函数,负责标签的切换。
void
view(const Arg *arg)
{
if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
return;
/* toggle sel tagset */
selmon->seltags ^= 1;
if (arg->ui & TAGMASK)
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
// user specific edit
prepareTag(arg->ui);
focus(NULL);
arrange(selmon);
}
我在调用prepareTag
的行中添加了一行。该功能具有简单的逻辑,除了进行几次验证(应用程序已打开?;它是什么标签?),其他所有操作之后,应用程序便会自动生成。
void
spawn(const Arg *arg)
{
if (arg->v == dmenucmd)
dmenumon[0] = '0' + selmon->num;
if (fork() == 0) {
if (dpy)
close(ConnectionNumber(dpy));
setsid();
execvp(((char **)arg->v)[0], (char **)arg->v);
fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
perror(" failed");
exit(EXIT_SUCCESS);
}
}
它可以工作,但是代码异步进行。更改标签后,我看到我的墙纸了,而不是在〜20-50ms之后启动了应用程序。它会引起明显的闪烁。问题是我从未使用过C,并且不知道代码异步工作的原因。我尝试使用system
函数代替内置的spawn
函数,但是dwm无法捕获以这种方式打开的应用程序。我可能可以使用键绑定器和一些BASH,但是方法很脏。更不用说,我希望能够使用鼠标按钮来更改标签。
万一有人需要代码库。
git clone https://git.suckless.org/dwm
答案 0 :(得分:1)
如果您阅读fork()
的手册,就会意识到它会创建正在运行的进程的副本。
在派生之后,两个过程彼此独立,并且可以按任何顺序进行调度。这是您看到的异步行为。
要获得同步行为,您的父进程需要等到派生进程完成(退出)。这可以通过wait()
系统调用来实现。
您可以将spawn
函数修改为-
void
spawn(const Arg *arg)
{
if (arg->v == dmenucmd)
dmenumon[0] = '0' + selmon->num;
if (fork() == 0) {
if (dpy)
close(ConnectionNumber(dpy));
setsid();
execvp(((char **)arg->v)[0], (char **)arg->v);
fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
perror(" failed");
exit(EXIT_SUCCESS);
} else { // fork returns a non zero pid in the parent process. So the else branch will be taken only in the parent.
wait(NULL); // Wait for the child process to change state. In this case exit
}
}