linux 进程通讯之信号

来源:互联网 发布:mac d for danger 编辑:程序博客网 时间:2024/05/01 11:48
1 查看系统所有信号的命令
  kill -l
2 查看某一个信号的值
  kill -l 信号名称
  例如: kill - l HUP
  
3 定义信号处理函数
  可以通过signal函数来注册处理函数。
  函数原型:sighandler_t signal(int signum , sighandler_t handler);
  参数:signum 为要处理的信号的值
        handler 该参数可以取三种值 1 SIG_IGN 表示忽略该信号
                                   2 SIG_DFL 表示恢复对信号的系统默认处理
                                   sighandler_t 信号处理函数的指针,指向我们自己定义的处理函数。
  返回值:信号处理函数指针,如果有错误则返回SIG_ERR(-1)。 
  
  sighandler_t定义如下
  typedef void (*sighandler_t)(int);
  是一个指向void fun(int para)类型的指针。
 
4 发送信号
  int kill(pid_t pid, int sig);  
  参数 pid 要发送到的程序的pid, 
       sig 要发送的信号值
  返回值:0成功,非0失败 ,常见的错误如下:
          给定的信号无效(errno = EINVAL)
        发送权限不够( errno = EPERM )
        目标进程不存在( errno = ESRCH )


6 示例代码:


void onsignal(int sig)  
{  
        switch(sig)
        {
                case 63:
                        printf("I get signal 63\n");
                        break;
                case 64:
                        printf("I get signal 64\n");
                        break;
        }
    
}
int main(int argc, char *argv[])
{
        return 0;
        signal(63, onsignal);  
        signal(64, onsignal); 
        while(1)
        {
                sleep(100);
        }
        return 0;
}
运行上面的程序,在命令行输入kill -63 pid 或者kill -64 pid
就可以看到下面的信息
I get signal 63 或者I get signal 64


7 通过程序名获取pid.
上面的例子是通过命令行发信号,如果要在程序中发信号,需要通过程序名称获取pid,下面是示例代码
int getpid_by_name( char* ProcName, int* foundpid ,int len)  
{  
        DIR             *dir;  
        struct dirent   *d;  
        int             pid, i;  
        char            *s;  
        int pnlen;  
  
        i = 0;  
        foundpid[0] = 0;  
        pnlen = strlen(ProcName);  
  
        /* Open the /proc directory. */  
        dir = opendir("/proc");  
        if (!dir)  
        {  
                printf("cannot open /proc");  
                return -1;  
        }  
  
        /* Walk through the directory. */  
        while ((d = readdir(dir)) != NULL) 
        {  
  
                char exe [PATH_MAX+1];  
                char path[PATH_MAX+1];  
                int len;  
                int namelen;  
  
                /* See if this is a process */  
                if ((pid = atoi(d->d_name)) == 0)continue;  
  
                snprintf(exe, sizeof(exe), "/proc/%s/exe", d->d_name);  
                if ((len = readlink(exe, path, PATH_MAX)) < 0)  
                        continue;  
                path[len] = '\0';  
  
                /* Find ProcName */  
                s = strrchr(path, '/');  
                if(s == NULL) continue;  
                s++;  
  
                /* we don't need small name len */  
                namelen = strlen(s);  
                if(namelen != pnlen)     continue;  
  
                if(!strncmp(ProcName, s, pnlen)) 
                {  
                        /* to avoid subname like search proc tao but proc taolinke matched */  
                        if( len>i)
                        {
                                foundpid[i] = pid;  
                                i++;  
                           
                        }  
                } 
        } 
        closedir(dir);  
  
        return  i;  
  
}  


8 示例代码
void onsignal(int sig)  
{  
        switch(sig)
        {
                case 63:
                        printf("I get signal 63\n");
                        break;
                case 64:
                        printf("I get signal 64\n");
                        break;
        }
    
}  
int main(int argc, char *argv[])
{
        if( argc>1)
        {
                signal(63, onsignal);  
                signal(64, onsignal); 
                while(1)
                {
                        sleep(100);
                }
        }
        else
        {
            int pid[5];
            int mypid;
            int otherpid;
            int ret;
            int find =0;
            while(1)
            {
                    ret = getpid_by_name("my-test",pid,5);
                     
                    if(ret>=2)
                    {
                            int i;
                            mypid=getpid();
                            for(i=0;i<ret;i++)
                            {
                                    if(mypid==pid[i])
                                    {
                                            continue;
                                    }
                                    else
                                    {
                                            otherpid=pid[i];
                                            find =1;
                                            break;
                                    }
                            }
                            if(find )
                            {
                                    break;
                            }
                            
                    }
                    else
                    {
                            sleep(5);
                    }
            }
            while(1)
            {
                    printf("send 63 to pid(%d)\n",otherpid);
                    kill(otherpid, 63);  
                    sleep(5);
                    printf("send 64 to pid(%d)\n",otherpid);
                    kill(otherpid, 64);  
                    sleep(5);
            }
        }
        
        return 0;
}
假设我们的程序名称为my-test
只要分别运行 my-test 1 &
和my-yest &
就可以看到交替打印
send 63 to pid(289)
I get signal 63
send 64 to pid(289)
I get signal 64
send 63 to pid(289)
I get signal 63
send 64 to pid(289)
I get signal 64
send 63 to pid(289)
I get signal 63
send 64 to pid(289)
I get signal 64
。。。。。