怎样通过signal在两个程序之间通信?

ruoly 2003-01-22 01:37:53
我是想通过这个程序修改一个文件,然后立刻发送信号
通知另一个程序去重新读取这个文件更新数据,望各位
高手指教!最好有c的例子,多谢!
...全文
83 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
NewAge 2003-01-24
  • 打赏
  • 举报
回复
互相学习
ruoly 2003-01-23
  • 打赏
  • 举报
回复
我的源代码:
程序一:是一个CGI程序,从网页接收2个整数输入,并保存,同时通知程序二读取该2个数据更新。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <process.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

int main()
{
extern int errno;
char *data;
int m,n;
pid_t pid;
FILE* fp;
int sss;

printf("Content-Type:text/html\n\n");
printf("<TITLE>乘法结果</TITLE>");
printf("<H3>乘法结果</H3>");
data = getenv("QUERY_STRING");
printf("<p>data is %s\n<BR>",data);
if(data == NULL)
{
printf("<P>错误!数据没有被输入或者数据传输有问题");
}
else
{
sscanf(data,"m=%d&n=%d",&m,&n);
printf("m is %d\n<BR>",m);
printf("n is %d\n<BR>",n);
printf("m*n is %d\n<BR>",m*n);
}
fp = fopen("/pp/shu","rb+");
fwrite(&m,sizeof(int),1,fp);
fwrite(&n,sizeof(int),1,fp);
fclose(fp);
fp = fopen("/pp/pid","rb+");
fread(&pid, sizeof(int),1,fp);
fclose(fp);
printf("pid is %d\n<BR>",pid);

sss = kill(pid,SIGUSR1);
printf("kill returns %d\n<br>",sss);
printf( "The error generated was %d\n<br>", errno );
printf( "That means: %s\n", strerror( errno ) );
return 0;
}

程序二:从指定文件获取数据并输出,当收到信号就重新读取数据输出。
#include "stdio.h"
#include <stdlib.h>
#include <signal.h>
#include <process.h>
void quit(int signo)
{
FILE* fp;
int m,n;
printf("Receive signal %d\n",signo);
fp = fopen("/pp/shu","rb+");
fread(&m,sizeof(int),1,fp);
fread(&n,sizeof(int),1,fp);
printf("m is %d\n",m);
printf("n is %d\n",n);
printf("n*m is %d\n",m*n);
fclose(fp);
}
int main()
{
FILE *fp;
FILE* fp2;
int m,n;
pid_t pp;
pp = getpid();
fp2 = fopen("/pp/pid","wb+");
fwrite(&pp,sizeof(int),1,fp2);
fclose(fp2);
if ((fp = fopen("/pp/shu","rb+")) == NULL)
{
fp = fopen("/pp/shu","wb+");
m = 2;
n = 3;
fwrite(&m,sizeof(int),1,fp);
fwrite(&n,sizeof(int),1,fp);
fclose(fp);
printf("Make a new file\n");
}
else
{
fread(&m,sizeof(int),1,fp);
fread(&n,sizeof(int),1,fp);
printf("mmm is %d\n",m);
printf("nnn is %d\n",n);
fclose(fp);
}

signal(SIGUSR1,quit);
kill(getpid(),SIGUSR1);
for (;;) {
sleep(3);
}
}

当程序二在后台运行时敲入命令行kill -USR1 pid没有问题数据输出立即就更新了,但是当通过运行程序一发送信号的时候,kill返回错误,根据捕获的errno说是这个进程没有permission发送信号给任何一个可以接收信号的程序。我是unix初学者,不明白是怎么回事。我难道还应该修改这个进程的权限么?
clientwyc 2003-01-23
  • 打赏
  • 举报
回复
如果这两个进程是处于同一个进程组的进程。
你就用 kill(0,SIGUSR1)
如果不是,那你可以用 kill(-1,SIGUSR1) 给进程表中的所有的进程发。(除第一个进程之外)
MarkSun 2003-01-23
  • 打赏
  • 举报
回复
可以通过pipe管道来解决,同时利用select(),这样可以消除另一个进程的忙等。process1对文件处理完毕之后,然后写管道。此时process2此时正在阻塞在读取管道线上。之后process2被唤醒。表示文件可以操作。当然,为了避免忙等。我们可以采用select()。这样,当管道可读时,或者select()超时process2都会被唤醒。
Qool 2003-01-23
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>


#define PERMS S_IRUSR|S_IWUSR
#define MAX_CANON 8

/*

struct sembuf
{
short sem_num; * 使用那一个信号 *
short sem_op; * 进行什么操作 *
short sem_flg; * 操作的标志 *
};

*/


void init_semaphore_struct(struct sembuf *sem,int semnum, int semop,int semflg)
{
/* 初始话信号灯结构 */
sem->sem_num = semnum;
sem->sem_op = semop;
sem->sem_flg = semflg;
}

int del_semaphore(int semid)
{
/* 信号灯并不随程序的结束而被删除,如果我们没删除的话(将1改为0)
可以用ipcs命令查看到信号灯,用ipcrm可以删除信号灯的
*/
#if 1
return semctl(semid,0,IPC_RMID);
#endif

}

int main(int argc,char **argv)
{
char buffer[MAX_CANON],*c;
int i,n;
int semid,semop_ret,status;
pid_t childpid;
struct sembuf semwait,semsignal;

if( (argc!=2) || ((n=atoi(argv[1]))<1) )
{
fprintf(stderr,"Usage:%s number\n\a",argv[0]);
exit(1);
}

/* 使用IPC_PRIVATE 表示由系统选择一个关键字来创建
创建以后信号灯的初始值为0 */

if((semid = semget(IPC_PRIVATE,1,PERMS))==-1)
{
fprintf(stderr,"[%d]:Acess Semaphore Error:%s\n\a",
getpid(),strerror(errno));
exit(1);
}

/* semwait是要求资源的操作(-1) */
init_semaphore_struct(&semwait,0,-1,0);

/* semsignal是释放资源的操作(+1) */
init_semaphore_struct(&semsignal,0,1,0);

/* 开始的时候有一个系统资源(一个标准错误输出) */
if(semop(semid,&semsignal,1)==-1)
{
fprintf(stderr,"[%d]:Increment Semaphore Error:%s\n\a",
getpid(),strerror(errno));

if(del_semaphore(semid)==-1)
{
fprintf(stderr,"[%d]:Destroy Semaphore Error:%s\n\a",
getpid(),strerror(errno));

}
exit(1);
}

/* 创建一个进程链 */
for(i=0;;i++)
{
if( childpid = fork())
break;
}

sprintf(buffer,"[i=%d]-->[Process=%d]-->[Parent=%d]-->[Child=%d]\n",
i,getpid(),getppid(),childpid);

c=buffer;

/* 这里要求资源,进入原子操作 */
while(((semop_ret=semop(semid,&semwait,1))==-1)&&(errno==EINTR));
if(semop_ret==-1)
{
fprintf(stderr,"[%d]:Decrement Semaphore Error:%s\n\a",
getpid(),strerror(errno));
}
else
{
while(*c!='\0') fputc(*c++,stderr);
/* 原子操作完成,赶快释放资源 */
while(((semop_ret=semop(semid,&semsignal,1))==-1)&&(errno==EINTR));

if(semop_ret==-1)
{
fprintf(stderr,"[%d]:Increment Semaphore Error:%s\n\a",
getpid(),strerror(errno));
}
}

/* 不能够在其他进程反问信号灯的时候,我们删除了信号灯 */
while((wait(&status)==-1)&&(errno==EINTR));

/* 信号灯只能够被删除一次的 */
if(i==1)
if(del_semaphore(semid)==-1)
fprintf(stderr,"[%d]:Destroy Semaphore Error:%s\n\a",
getpid(),strerror(errno));
exit(0);
}

建议你好好看看此程序比较经典的丫

有什么需要可以email :
mr_king@etang.com


core 2003-01-23
  • 打赏
  • 举报
回复
IPC的方法有很多,非要用signal的,见识了一回
Nvram 2003-01-23
  • 打赏
  • 举报
回复
在你的信号处理程序quit()的结尾在调用一遍
signal(SIGUSR1,quit);
clientwyc 2003-01-22
  • 打赏
  • 举报
回复
用raise(SIGUSR1)看看!
blh 2003-01-22
  • 打赏
  • 举报
回复
用kill调用
ruoly 2003-01-22
  • 打赏
  • 举报
回复
要求必须使用signal
信号处理的程序已经做好,但是在程序内发送信号还有问题
pid是通过读写文件获得的
我在命令行下输入kill -USR1 pid就没有问题
但是在程序中使用kill(pid,SIGUSR1)就不行
返回值是-1,捕获errno,是说操作不被允许
但是我是用root的啊,不应该没有权限吧?
clientwyc 2003-01-22
  • 打赏
  • 举报
回复
用消息队列来监控,你修改文件后就发一个消息包到某个队列里
而另一个进程读该队列,有符合的消息码,你就去重新读取这个文件更新数据。
Nvram 2003-01-22
  • 打赏
  • 举报
回复
从你的需求来看用共享内存更合适一些。
95533 2003-01-22
  • 打赏
  • 举报
回复
简单啊!
直接向那个程序发送SIG_USER1信号,那个程序增加SIG_USER!1信号的处理就行了。

23,116

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧