- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个用 C 语言编写的程序。它必须创建 3 个始终工作的进程。这 3 个进程接收信号(停止、暂停、恢复),当它接收到其中一个信号时,它会向其余进程发送其他信号,然后将他收到的信号写入管道(必须是管道)。其他人收到该信号并读取管道并执行管道中所说的操作。我有类似的东西可以在信号处理程序中编写一个管道:
void rcvkillsig(int sig){
if(sig==SIGINT){
int op;
op = 1;
close(pfd1[0]);
close(pfd3[0]);
write(pfd1[1], &op, 8);
write(pfd3[1], &op, 8);
close(pfd1[1]);
close(pfd3[1]);
kill(sndpid, SIGCONT);
kill(rcvpid, SIGCONT);
printf("End chk\n");
kill(chkpid, SIGKILL);
}
}
还有类似读取管道的东西:
void rcvinfsig(int sig){
if(sig==SIGCONT){
cflag=0;
int op;
close(pfd2[1]);
read(pfd2[0], &op, 8);
close(pfd2[0]);
if(op==1){
kill(chkpid, SIGKILL);
printf("End chk\n");
}
else if(op==2){
printf("Pause chk!\n");
cpaused=1;
}
else if(op==3){
printf("Resume chk!\n");
cpaused=0;
}
}
}
当然每个进程和接收到的信号都有这样的代码。
我在这个程序中为每个进程使用 pfd1[2]、pfd2[2]、pfd3[2],并在主函数中通过 pipe(...) 为它们创建管道。
我的问题是,当进程接收到第一个信号(例如暂停)时,他写入管道,但是当它接收到第二个信号(例如恢复)时,它不写入管道,只恢复自身。
请帮助我在星期一需要那个程序。其余的代码都可以工作,而我并没有只有那种沟通方式。
最佳答案
根据发布的函数,我认为您的代码中存在两个主要问题。
<强>1。您在每次调用信号处理程序时关闭文件描述符。
这不是个好主意 - 每次读取或写入后关闭文件描述符。单向管道不能以这种方式工作。创建描述符对后您应该在一个进程中关闭第一个描述符,在另一个进程中关闭第二个描述符。这将创建一个从第一个进程到第二个进程的管道(man pipe)。在手册页的示例中,他们关闭了描述符写完之后,因为他们不再需要它了。
<强>2。好像你只有 3 对文件描述符。
通过单向管道连接 3 个进程(如下图所示),需要 6 对描述符:
fd 5,6
+------------+ +------------+
| |<----------| |
| process #0 | | process #1 |
| |---------->| |
+------------+ +------------+
| ^ fd 7,8 | ^
| | | |
fd 1,2 | | fd 3,4 fd 9,10 | | fd 11,12
| | | |
v | | |
+------------+ | |
| |<--------------+ |
| process #2 | |
| |-------------------+
+------------+
示例。
这是一个代码示例,它做同样的事情。它与好的示例相差甚远(信号处理程序中的错误信号处理,printf
),但我希望它能有所帮助。
int g_pfd[3][2][2]; // pairs of file desriptors.
volatile sig_atomic_t g_ignore_sighup = 0; // flag for ignoring SIGHUP
void ( * g_handlers[3] ) ( int ); // array of signal handlers
void sig_handler ( int signo, int id )
{
if ( signo == SIGHUP )
{
if ( g_ignore_sighup )
{
g_ignore_sighup = 0;
return;
}
printf ( "SIGHUP recvd, pid = %d\n", getpid () );
int rd1 = ( id );
int rd2 = ( id == 0 ? 2 : id - 1 );
// choose, which process sent SIGHUP.
fd_set rfds;
FD_ZERO ( &rfds );
FD_SET ( g_pfd[rd1][1][0], &rfds );
FD_SET ( g_pfd[rd2][0][0], &rfds );
int rv = select ( FD_SETSIZE, &rfds, NULL, NULL, NULL );
if ( rv == -1 )
{
perror ( "select" );
return;
}
else if ( rv == 0 )
{
return;
}
int fd = -1;
if ( FD_ISSET ( g_pfd[rd1][1][0], &rfds ) ) fd = g_pfd[rd1][1][0];
if ( FD_ISSET ( g_pfd[rd2][0][0], &rfds ) ) fd = g_pfd[rd2][0][0];
int i;
if ( read ( fd, &i, sizeof ( int ) ) == -1 )
{
perror ( "read" );
}
printf ( "recvd data through pipe = %d\n", i );
return;
}
if ( signo == SIGINT )
{
int wr1 = ( id );
int wr2 = ( id == 0 ? 2 : id - 1 );
printf ( "SIGINT recvd, pid = %d\n", getpid () );
printf ( "write: %d to %d\n", getpid (), g_pfd[wr1][0][1] );
printf ( "write: %d to %d\n", getpid (), g_pfd[wr2][1][1] );
int pid = getpid ();
if ( write ( g_pfd[wr1][0][1], &pid, sizeof ( int ) ) == -1 ||
write ( g_pfd[wr2][1][1], &pid, sizeof ( int ) ) == -1 )
{
perror ( "write" );
}
g_ignore_sighup = 1; // flag for ignorig own signal
// send SIGHUP to parent and all its children.
if ( kill ( 0, SIGHUP ) == -1 )
{
perror ( "kill" );
}
return;
}
}
void sig_handler_0 ( int signo ) { sig_handler ( signo, 0 ); }
void sig_handler_1 ( int signo ) { sig_handler ( signo, 1 ); }
void sig_handler_2 ( int signo ) { sig_handler ( signo, 2 ); }
int create_process ( int *pid, int id )
{
*pid = fork ();
if ( *pid == -1 )
{
perror ( "fork" );
return 1;
}
if ( *pid != 0 ) // parent
{
return 0;
}
// close appropriate descriptors
int i1 = ( id );
int i2 = ( id == 0 ? 2 : id - 1 );
close ( g_pfd[i1][0][0] );
close ( g_pfd[i2][0][1] );
close ( g_pfd[i1][1][1] );
close ( g_pfd[i2][1][0] );
if ( signal ( SIGINT, g_handlers[id] ) == SIG_ERR ||
signal ( SIGHUP, g_handlers[id] ) == SIG_ERR )
{
perror ( "signal" );
return 1;
}
while ( 1 ) sleep ( 1 );
exit ( 0 );
}
int main ( int argc, char *argv [] )
{
// fill array of signal handlers.
g_handlers[0] = sig_handler_0;
g_handlers[1] = sig_handler_1;
g_handlers[2] = sig_handler_2;
if ( signal ( SIGHUP, SIG_IGN ) == SIG_ERR )
{
perror ( "signal" );
return 1;
}
int pid [3];
int i, j;
// create pairs of descriptors
for ( i = 0; i < 3; i++ )
{
for ( j = 0; j < 2; j++ )
{
if ( pipe ( g_pfd[i][j] ) == -1 )
{
perror ( "pipe" );
return 1;
}
}
}
if ( create_process ( &pid[0], 0 ) != 0 ||
create_process ( &pid[1], 1 ) != 0 ||
create_process ( &pid[2], 2 ) != 0 )
{
return 1;
}
sleep ( 1 );
kill ( pid[0], SIGINT ); sleep ( 3 );
kill ( pid[1], SIGINT ); sleep ( 3 );
kill ( pid[2], SIGINT );
wait ( NULL );
for ( i = 0; i < 3; i++ )
{
for ( j = 0; j < 2; j++ )
{
close ( g_pfd[i][j][0] );
close ( g_pfd[i][j][1] );
}
}
return 0;
}
关于c - Linux C 使用信号和管道在进程间通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17127819/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
Linux 管道可以缓冲多少数据?这是可配置的吗? 如果管道的两端在同一个进程中,但线程不同,这会有什么不同吗? 请注意:这个“同一个进程,两个线程”的问题是理论上的边栏,真正的问题是关于缓冲的。 最
我找到了here [最后一页] 一种有趣的通过 Linux 启动 Linux 的方法。不幸的是,它只是被提及,我在网上找不到任何有用的链接。那么有人听说过一种避免引导加载程序而使用 Linux 的方法
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我试图了解 ld-linux.so 如何在 Linux 上解析对版本化符号的引用。我有以下文件: 测试.c: void f(); int main() { f(); } a.c 和 b.c:
与 RetroPie 的工作原理类似,我可以使用 Linux 应用程序作为我的桌面环境吗?我实际上并不需要像实际桌面和安装应用程序这样的东西。我只需要一种干净简单的方法来在 RaspberryPi 上
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
有什么方法可以覆盖现有的源代码,我应该用 PyQt、PyGTK、Java 等从头开始构建吗? 最佳答案 如果您指的是软件本身而不是它所连接的存储库,那么自定义应用程序的方法就是 fork 项目。据我所
我的情况是:我在一个磁盘上安装了两个 linux。我将第一个安装在/dev/sda1 中,然后在/dev/sda2 中安装第二个然后我运行第一个系统,我写了一个脚本来在第一个系统运行时更新它。
我在 i2c-0 总线上使用地址为 0x3f 的系统监视器设备。该设备在设备树中配置有 pmbus 驱动程序。 问题是,加载 linux 内核时,这个“Sysmon”设备没有供电。因此,当我在总线 0
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve thi
我正试图在 linux 模块中分配一大块内存,而 kalloc 做不到。 我知道唯一的方法是使用 alloc_bootmem(unsigned long size) 但我只能从 linux 内核而不是
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我有 .sh 文件来运行应用程序。在该文件中,我想动态设置服务器名称,而不是每次都配置。 我尝试了以下方法,它在 CentOS 中运行良好。 nohup /voip/java/jdk1.8.0_71/
我是在 Linux 上开发嵌入式 C++ 程序的新手。我有我的 Debian 操作系统,我在其中开发和编译了我的 C++ 项目(一个简单的控制台进程)。 我想将我的应用程序放到另一个 Debian 操
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 4 年前。 Improve this ques
我使用4.19.78版本的稳定内核,我想找到带有企鹅二进制数据的C数组。系统启动时显示。我需要在哪里搜索该内容? 我在 include/linux/linux_logo.h 文件中只找到了一些 Log
我知道可以使用 gdb 的服务器模式远程调试代码,我知道可以调试针对另一种架构交叉编译的代码,但是是否可以更进一步,从远程调试 Linux 应用程序OS X 使用 gdbserver? 最佳答案 当然
是否有任何可能的方法来运行在另一个 Linux 上编译的二进制文件?我知道当然最简单的是在另一台机器上重建它,但假设我们唯一能得到的是一个二进制文件,那么这可能与否? (我知道这可能并不容易,但我只是
我是一名优秀的程序员,十分优秀!