- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试重新编码 UNIX 命令 script
(因为它在 OSX 上)。这是学校帮助学生学习 UNIX API 的练习的一部分。我们只能使用系统调用,更具体地说,只能使用 Mac OSX 上 MAN(2) 页面上可用的系统调用(因为这是我们学校的操作系统)。
我有一个这样的作品的“第一版”。运行诸如 ls
之类的程序会将正确的输出打印到屏幕和输出文件中。
问题场景
我从 script
克隆中运行 bash
。第一个问题是我收到以下错误:
bash:此 shell 中没有作业控制
我已经尝试使用 setpgrp
和 setpgid
将 bash
进程强制进入前台,但这并没有改变任何东西,所以我得出结论,这不是问题。
我也试图理解为什么真正的 script
命令使用 cfmakeraw
(至少在 Linux 上),如 here 所示,但我不明白。 MAN 页面不是很有帮助。
真正的脚本
也是dup2
在slave
上的STDIN,如here所示,但是当我这样做时,似乎不再读取输入。
但是,bash 仍在运行,我可以在其中执行命令。
但是如果我在其中运行 vim
,然后按 Ctrl-Z 将 vim
置于后台,终端就会困惑(当我'在我的常规终端中)。
所以我想我一定做错了什么。如果有任何建议/帮助,我将不胜感激。
您可以通过以下方式进行编译:make
(它基于 OSX 10.9,希望也适用于 Linux)
然后运行:./ft_script
不知道将所有源代码放在 StackOverflow 中更有意义,因为它会挤满页面。如果需要,我可以用源代码替换 Git 链接。
最佳答案
我不使用 OS X,所以我不能直接测试你的代码,但我目前正在编写一个玩具终端模拟器并且遇到了类似的麻烦。
关于“bash:此 shell 中没有作业控制”
为了执行作业控制,shell 需要是其终端的 session 领导者 和控制进程。默认情况下,您的程序会继承您自己的 shell 的控制终端,该终端运行您的 script
程序,它也是 session 领导者。以下是如何在 fork
之后使您的新从属进程成为 session 领导者:
/* we don't need the inherited master fd */
close(master);
/* discard the previous controlling tty */
ioctl(0, TIOCNOTTY, 0);
/* replace existing stdin/out/err with the slave pts */
dup2(slave, 0);
dup2(slave, 1);
dup2(slave, 2);
/* discard the extra file descriptor for the slave pts */
close(slave);
/* make the pts our controlling terminal */
ioctl(0, TIOCSCTTY, 0);
/* make a new session */
setsid()
此时, fork 进程将stdin/out/err 绑定(bind)到新的pts,pts 成为它的控制终端,进程是 session 领导者。作业控制现在应该可以工作了。
关于原始 tty
当您在普通终端中运行程序时,它看起来像这样:
(term emulator, master side) <=> /dev/pts/42 <=> (program, slave side)
如果您按^Z
,终端仿真器会将ascii 字符0x1A
写入pts。它是一个控制字符,因此不会发送给程序,而是内核会向程序发出SIGSTP
并暂停它。将字符转换成其他东西的过程称为“线 cooking ”,并且具有可以针对每个 tty 进行调整的各种设置。
现在让我们看看脚本
的情况:
term emulator <=> /dev/pts/42 <=> script <=> /dev/pts/43 <=> program
在正常的线路设置下,当您按下 ^Z
时会发生什么?会被/dev/pts/42
转化为SIGSTP
,script
会被挂起。但这不是我们想要的,相反,我们希望 ^Z
生成的 0x1A
字符按原样通过 /dev/pts/42
,然后被script
传递给/dev/pts/43
,然后才被转化为SIGSTP
来暂停程序。
这就是为什么你的终端和脚本之间的点必须配置为“原始”的原因,这样所有的控制字符都可以到达脚本
和程序之间的点,就像你直接工作一样与它。
关于克隆命令 `script` 和 PTY 后台作业问题 : terminal messed up,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23443159/
从 0 开始搭建一套后台管理系统,成本巨大,所以都会选择一套成熟的组件库,基于此,再堆叠业务逻辑。我们公司的组件库基于 Ant Design。Ant Design 包含一套完整的后台解决方案,不仅
在我的 IOS 应用程序中,我有一个标记为 retain 的 NSDate* 属性 当我的应用程序再次激活时,属性值已被释放。 我是否误解了属性和内存管理的工作原理,我该如何防范? 最佳答案 很明显,
我有一个使用 BackgroundWorker 组件的示例 WinForms 应用程序。它工作正常,但是当我点击 Cancel 按钮取消后台线程时,它并没有取消线程。当我点击 Cancel 按钮调用
我目前正在开发一个应用程序,该应用程序在启动时会对服务器执行 ping 操作,该服务器会为每个连接的设备返回一个唯一标识符。设备每 5 秒从服务器检索另一页以获取一组不同的数据。这个唯一的 ID 可以
我正在开发一个应用程序,当它通过主页按钮在后台按下时,计时器应该启动,当应用程序返回前台并且计时器已经过了一定时间时,应该是执行。 我的问题是 当我的应用程序转到背景/前景? 是否有特殊的方法或其他技
我有 map View ,其中几乎没有 MKPointAnnotation。 一切正常,但是, View 的 MKPoiintAnnotation 的“背景”是“不可见的”,因此不是很“可见”。 我想
我在 iOS 中开发广告数据应用程序。我的应用程序广告数据在前台很好。但我想在 ios 后台宣传信标数据。我设置了背景外设设置。和广告数据 advertisingData = [CBAdvertise
如果我有一组操作,我想根据特定条件在后台工作程序中运行,例如,我有 10 个条件 if(a) BackgroundWorker doA = new backgroundworker() if(
我想独立运行一个函数。从我调用的函数中,我想在不等待其他函数结束的情况下返回。 我试过用 threadind,但这会等待,结束。 thread = threading.Thread(target=my
我想在用户在线时立即执行一些任务,即使他在后台也是如此。我正在使用 Reachability 类来检查互联网。但是当我在后台时,这个类没有通知我。我知道有人早些时候问过这个问题,但没有找到任何解决方案
我在后台播放文本转语音时出现间歇性(哎呀!)问题,由 Apple Watch 触发。我已经正确设置了后台模式、AVSession 类别和 WatchKitExtensionRequest 处理程序。
我有一个相当复杂的程序,所以我不会在这里转储整个程序。这是一个简化版本: class Report { private BackgroundWorker worker; public
我有一个任务在 backgroundworker 中运行。单击开始按钮,用户将启动该过程,并获得一个取消按钮来取消处理。 当用户点击取消时,我想显示一个消息框“进程尚未完成,你想继续吗”。 这里我希望
我有一个按以下方式编码的脚本。我想将它作为后台/守护进程运行,但是一旦我启动脚本,如果我关闭它从程序运行的终端窗口终止。我需要做什么来保持程序运行 loop do pid = fork do
我正在制作一个使用 ActivityRecognition API 在后台跟踪用户 Activity 的应用,如果用户在指定时间段(例如 1 小时)内停留在同一个地方,系统就会推送通知告诉用户去散步.
当尝试使用 URLSession 的 dataTaskPublisher 方法发送后台请求时: URLSession(configuration: URLSessionConfiguration.ba
当我编译这段代码时,我得到了他的错误,对象引用设置为null,错误位置在Dowork中,argumenttest.valueone = 8; public partial class Form1 :
有什么方法可以使用最小化或不活动的应用程序吗?我可以打开我的应用程序,然后打开并使用另一个应用程序,然后按一个按钮来激活我的程序吗? 例如,打开我的应用程序,打开 Safari,按下按钮(F1 或任何
我的具体要求是一个在后台运行的应用程序,被通知显示器即将进入休眠状态或者设备已经或即将达到空闲超时 - 然后唤醒并执行一些(简短的)一段代码。 我在这里找到了有关应用程序被置于后台或暂停的通知的引用:
我有一个 LSUIElement 设置为 1 的应用程序。它有一个内置编辑器,因此我希望该应用程序在编辑器打开时出现在 Cmd+Tab 循环中。 -(void)stepIntoForegrou
我是一名优秀的程序员,十分优秀!