- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在大学里学到了在后台处理进程的最简单方法,即使用管道 read 挂起子/父进程 的运行()
函数。老实说,我已经做作业 2 周了,我无法解决异步进程处理。我最小化了我的代码,使用 2 个管道编写单个子进程,并使用 read()
函数阻止父进程和子进程。您可以在下面找到我的代码的当前状态:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char pipeMessage[100];
char* readFromPipe(int pipe)
{
pipeMessage[0] = '\0';
read(pipe, pipeMessage, sizeof(pipeMessage));
fflush(NULL);
return pipeMessage;
}
void writeToPipe(int pipe, char *input)
{
char text[strlen(input) + 1];
strncpy(text, input, (int)strlen(input));
strncat(text, "\0", 1);
printf("TEXT: %s\n", text);
write(pipe, text, sizeof(text));
fflush(NULL);
}
int main(void)
{
int pipes[2][2];
pid_t pid;
if(pipe(pipes[0]) < 0 || pipe(pipes[1]) < 0)
{
printf("[ERROR] create pipes\n");
return -1;
}
printf("[PARENT] Create child1\n");
if((pid = fork()) < 0)
{
printf("[ERROR] Fork error\n");
return -1;
}
if(pid == 0)
{
// Child code
close(pipes[0][0]);
writeToPipe(pipes[0][1], "TEST MESSAGE");
printf("[CHILD1] pipe message: %s\n", readFromPipe(pipes[1][0]));
writeToPipe(pipes[0][1], "-1");
}
else if(pid > 0)
{
// Parent code
close(pipes[0][1]);
close(pipes[1][0]);
char *message;
do
{
message = readFromPipe(pipes[0][0]);
printf("[PARENT] pipe message: %s\n", message);
writeToPipe(pipes[1][1], "-1");
}
while(atoi(message) != -1);
}
return 0;
}
错误如下:
[PARENT] Create child1
TEXT: TEST MESSAGE
[PARENT] pipe message: TEST MESSAGE
TEXT: -1
[CHILD1] pipe message: -1
TEXT: -1�po
[PARENT] pipe message: -1�T MESSAGE
TEXT: -1�po
我尝试用信号实现这个进程处理,但在最终的应用程序中我需要 3 个不同的子进程,异步运行导致信号处理出现问题。我也试图在网上找到一个教程,但每个多处理主题都涵盖了从父到子的简单单消息解决方案,反之亦然。但是我在父进程中需要一个基于字符的菜单,所以 children 应该不断等待父信号/消息,而 parent 也需要等待 child 完成实际任务。请帮助我,因为我真的被困住了。如果您有任何正常的流程处理解决方案,请告诉我,因为我知道这段代码很糟糕。唯一的原因是缺乏正确的教程。提前致谢。
最佳答案
您的编写逻辑有问题,管道布局过于复杂。下面是你的代码,根据我能收集到的最简单的案例进行定制。包含评论以帮助您。我发现在处理链式管道(对于所有意图而言正是它)时最简单的方法是布置一个由展示链接的宏索引的描述符数组:
// some hand macros for access the correct pipes
#define P_READ 0
#define C_WRITE 1
#define C_READ 2
#define P_WRITE 3
#define N_PIPES 4
以上将在最终源列表中。名字对象应该是不言自明的,但如果不是,P_XXX
说明parent 进程使用的管道,C_XXX
说明管道child 进程使用。看到代码时请记住这一点:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
// some hand macros for access the correct pipes
#define P_READ 0
#define C_WRITE 1
#define C_READ 2
#define P_WRITE 3
#define N_PIPES 4
// reads a buffer up-to len size.
ssize_t readFromPipe(int pipe, char *buff, size_t len)
{
buff[0] = 0;
ssize_t res = read(pipe, buff, len);
assert(res >= 0 && "Failed to read from pipe");
return res;
}
ssize_t writeToPipe(int pipe, const char *input)
{
size_t len = strlen(input)+1;
ssize_t res = write(pipe, input, len);
assert(res == len && "Failed to write to pipe");
return res;
}
int main(void)
{
int pipes[N_PIPES];
char msg[128] = {0};
pid_t pid;
if(pipe(pipes) < 0 || pipe(pipes+2) < 0)
{
printf("[ERROR] create pipes\n");
return EXIT_FAILURE;
}
if((pid = fork()) < 0)
{
printf("[ERROR] Fork error\n");
return EXIT_FAILURE;
}
// parent code
if(pid > 0)
{
// Parent code. close down the child pipes; don't need them
printf("parent(%d) create: child(%d)\n", getpid(), pid);
close(pipes[C_WRITE]);
close(pipes[C_READ]);
do
{
if (readFromPipe(pipes[P_READ], msg, sizeof(msg)) > 0)
{
printf("parent(%d) read : %s\n", getpid(), msg);
writeToPipe(pipes[P_WRITE], "-1");
}
else break;
}
while(atoi(msg) != -1);
// close remaining pipes. no longer needed
close(pipes[P_READ]);
close(pipes[P_WRITE]);
}
else if(pid == 0)
{
// Child code. don't need parent write or child-read lines
close(pipes[P_READ]);
close(pipes[P_WRITE]);
// write message
writeToPipe(pipes[C_WRITE],"test message");
// read test message
if (readFromPipe(pipes[C_READ], msg, sizeof(msg)) > 0)
printf("child(%d) read : %s\n", getpid(), msg);
// write another message
writeToPipe(pipes[C_WRITE], "-1");
// close remaining pipes. no longer needed
close(pipes[C_READ]);
close(pipes[C_WRITE]);
}
return EXIT_SUCCESS;
}
不支持管道描述符数组,其中最大的变化是简化了writeToPipe
逻辑,它只是向管道写入一个终止符C字符串,包括终止空字符。
ssize_t writeToPipe(int pipe, const char *input)
{
size_t len = strlen(input)+1;
ssize_t res = write(pipe, input, len);
assert(res == len && "Failed to write to pipe");
return res;
}
调用者检查结果以确保它写入了所有请求的数据,并且嵌入式 assert() 宏将在失败时触发调试器。读取功能存在类似的逻辑。
输出(因进程 ID 而异)
parent(2067) create: child(2068)
parent(2067) read : test message
child(2068) read : -1
parent(2067) read : -1
希望对您有所帮助。在处理管道时,特别是在不久的将来您可能会遇到的 stdio 重定向 ( see spoiler here ) 时,为您的代码提供有意义的助记符非常有帮助,例如我在上面使用的宏索引管道数组。
祝你好运。
关于c - GNU C 使用管道的多进程处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27672109/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!