c - 如何同步调用shell命令?
问题描述
我正在尝试教 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-50 毫秒后启动了应用程序。它会导致明显的闪烁。问题是我从未使用过 C,也不知道代码异步工作的原因。我尝试过system
使用函数而不是内置的,spawn
但 dwm 不会捕获以这种方式打开的应用程序。我可能可以使用键绑定器和一些 BASHing,但方法很脏。更不用说,我希望能够使用鼠标按钮来更改标签。
如果有人需要代码库。
git clone https://git.suckless.org/dwm
解决方案
如果您阅读了 的手册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
}
}
推荐阅读
- facebook - 如何集成 Facebook Messenger 群组对话?
- docker - Docker 绑定挂载目录中的文件未更新
- jmeter - 如何在仪表板页面中动态获取 Jmeter 版本和 Java 版本
- json - 如何使用 shell jq 动态解析 JSON 对象
- android - webview 弹出窗口中的内容隐藏在键盘后面(请阅读特殊情况)
- python - 为什么存在参数时 Django 2.1 login_required 不起作用
- php - 需要一些关于 php curl 的信息
- html - Html CSS 表单改变背景
- regex - Pyspark 路径正则表达式负前瞻
- sql - 使用分区查询复制数据