微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在Linux和Windows上,进程pipe理代码的performance有所不同 – 为什么?

(上下文)我正在开发一个基于BitTorrent Sync的跨平台(Windows和Linux)应用程序,用于在计算机之间分发文件。 我已经在C#中完成了,现在正在向C ++移植。

BTSync可以在API模式下启动,为此,必须启动“ btsync ”可执行文件,将configuration文件名称和位置作为parameter passing。

在这一点上,我最大的问题是让我的应用程序处理可执行文件。 在寻找一个跨平台的stream程pipe理库的时候,我已经find了Boost.Process ,并决定尝试一下。 看来v0.5是最新的工作版本,正如有证据表明的那样,有很多人在使用它。

我按如下方式实现了库(仅适用于相关代码):

在32位debian系统上生成64位代码

Golang为Windows 7中的所有平台编译(32位)

我如何制作一个Java跨平台的GUI应用程序(Windows,Linux)? 我应该使用什么工具?

在Linux和Linux上build立一个开发环境

自动文件从Linux机器复制到Windows机器

文件: test.hpp

namespace testingBoostProcess { class Test { void StartSyncing(); }; }

文件: Test.cpp

#include <string> #include <vector> #include <iostream> #include <boost/process.hpp> #include <boost/process/mitigate.hpp> #include "test.hpp" using namespace std; using namespace testingBoostProcess; namespace bpr = ::boost::process; #ifdef _WIN32 const vector<wstring> EXE_NAME_ARGS = { L"btsync.exe",L"/config",L"conf.json" }; #else const vector<string> EXE_NAME_ARGS = { "btsync","--config","conf.json" }; #endif void Test::StartSyncing() { cout << "Starting Server..."; try { bpr::child exeServer = bpr::execute(bpr::initializers::set_args(EXE_NAME_ARGS),bpr::initializers::throw_on_error(),bpr::initializers::inherit_env()); auto exitStatus = bpr::wait_for_exit(exeServer); // type will be either DWORD or int int exitCode = BOOST_PROCESS_EXITSTATUS(exitStatus); cout << " ok" << "tstatus: " << exitCode << "n"; } catch (const exception& excStartExeServer) { cout << "n" << "Error: " << excStartExeServer.what() << "n"; } }

(问题)在Windows上,上述代码将启动btsync并等待(阻止),直到进程终止(通过使用任务pipe理器或通过API的shutdown方法),就像所期望的一样。

但是在Linux上,它在启动进程后立即结束执行,就好像wait_for_exit()根本就不存在,虽然btsync进程没有终止。

在试图看看这是否与btsync可执行文件本身有关,我用这个简单的程序取代了它:

File: Fake-Btsync.cpp

#include <cstdio> #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define SLEEP Sleep(20000) #include <Windows.h> #else #include <unistd.h> #define SLEEP sleep(20) #endif using namespace std; int main(int argc,char* argv[]) { for (int i = 0; i < argc; i++) { printf(argv[i]); printf("n"); } SLEEP; return 0; }

当使用这个程序,而不是从官方网站下载的原始btsync ,我的应用程序按需工作。 它会阻塞20秒,然后退出

问题:描述行为的原因是什么? 我唯一能想到的就是btsync在Linux上重新启动。 但如何确认? 还有什么可能呢?

更新:我所需要做的就是知道什么是分叉 ,以及它是如何工作的,正如sehe的答案(谢谢!)所指出的那样。

问题2:如果我的主应用程序被阻塞的时候,如果我使用系统监视器发送一个End命令给subprocess' Fake-Btsync ',那么wait_for_exit()会抛出一个exception:

waitpid(2)失败:没有subprocess

这是一个不同于Windows上的行为,它只是简单地说“ok”,而终止于状态0。

更新2: sehe的答案很好,但是我没有完全按照我能理解的方式来解决问题2。 我会写一个关于这个问题的新问题,并在这里发布链接

C编程 – Linux和OSX之间的区别

Android / Windows混合应用程序

移植到不同架构的潜在问题

可以在unix上使用WPF吗?

重命名函数vs undef:与Windows API冲突

问题是你对btsync的假设。 我们开始吧:

./btsync By using this application,you agree to our Privacy Policy,Terms of Use and End User License Agreement. http://www.bittorrent.com/legal/privacy http://www.bittorrent.com/legal/terms-of-use http://www.bittorrent.com/legal/eula BitTorrent Sync forked to background. pid = 24325. default port = 8888

所以,这就是整个故事: BitTorrent Sync forked to background 。 而已。 没有什么。 如果你想, btsync --help告诉你传递--nodaemon 。

测试过程终止

让我们通过--nodaemon使用测试程序运行btsync 。 在一个单独的子shell中,让我们在5秒后杀死子进程:

sehe@desktop:/tmp$ (./test; echo exit code $?) & (sleep 5; killall btsync)& time wait [1] 24553 [2] 24554 By using this application,Terms of Use and End User License Agreement. http://www.bittorrent.com/legal/privacy http://www.bittorrent.com/legal/terms-of-use http://www.bittorrent.com/legal/eula [20141029 10:51:16.344] total physical memory 536870912 max disk cache 2097152 [20141029 10:51:16.344] Using IP address 192.168.2.136 [20141029 10:51:16.346] Loading config file version 1.4.93 [20141029 10:51:17.389] UPnP: Device error "http://192.168.2.1:49000/l2tpv3.xml": (-2) [20141029 10:51:17.407] UPnP: ERROR mapping TCP port 43564 -> 192.168.2.136:43564. Deleting mapping and trying again: (403) UnkNown result code (UPnP protocol violation?) [20141029 10:51:17.415] UPnP: ERROR removing TCP port 43564: (403) UnkNown result code (UPnP protocol violation?) [20141029 10:51:17.423] UPnP: ERROR mapping TCP port 43564 -> 192.168.2.136:43564: (403) UnkNown result code (UPnP protocol violation?) [20141029 10:51:21.428] Received shutdown request via signal 15 [20141029 10:51:21.428] Shutdown. Saving config sync.dat Starting server... ok status: 0 exit code 0 [1]- Done ( ./test; echo exit code $? ) [2]+ Done ( sleep 5; killall btsync ) real 0m6.093s user 0m0.003s sys 0m0.026s

没问题!

一个更好的假Btsync

这应该仍然是可移植的,并且在死亡/终止/中断时表现得更好(更好):

#include <boost/asio/signal_set.hpp> #include <boost/asio.hpp> #include <iostream> int main(int argc,char* argv[]) { boost::asio::io_service is; boost::asio::signal_set ss(is); boost::asio::deadline_timer timer(is,boost::posix_time::seconds(20)); ss.add(SIGINT); ss.add(SIGTERM); auto stop = [&]{ ss.cancel(); // one of these will be redundant timer.cancel(); }; ss.async_wait([=](boost::system::error_code ec,int sig){ std::cout << "Signal received: " << sig << " (ec: '" << ec.message() << "')n"; stop(); }); timer.async_wait([&](boost::system::error_code ec){ std::cout << "Timer: '" << ec.message() << "'n"; stop(); }); std::copy(argv,argv+argc,std::ostream_iterator<std::string>(std::cout,"n")); is.run(); return 0; }

你可以测试它是否表现良好

(./btsync --nodaemon; echo exit code $?) & (sleep 5; killall btsync)& time wait

同样的测试可以使用“官方” btsync和“假” btsync 。 输出在我的Linux机器上:

sehe@desktop:/tmp$ (./btsync --nodaemon; echo exit code $?) & (sleep 5; killall btsync)& time wait [1] 24654 [2] 24655 ./btsync --nodaemon Signal received: 15 (ec: 'Success') Timer: 'Operation canceled' exit code 0 [1]- Done ( ./btsync --nodaemon; echo exit code $? ) [2]+ Done ( sleep 5; killall btsync ) real 0m5.014s user 0m0.001s sys 0m0.014s

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐