linux进程通信 共享内存 信号

linux进程通信 共享内存 信号

一.共享内存

在这里插入图片描述
原理:A,B两个进程虽然各自内存空间不同。但是共享内存的内容同样利用映射之后再用指针挂载上去。这样可以做到A在共享内存里写数据,B马上就可以读取到。

共享内存的API

在这里插入图片描述

写入共享内存:

**#include <sys/shm.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include<string.h>
int main(){
key_t key;
key=ftok(".",1);          //获得key值
char* addr;                 //指向映射共享内存的指针
int shmID;
shmID=shmget(key,sizeof(4*1024),IPC_CREAT|0666 );
addr=shmat(shmID,0,0);  //两个0都指向系统默认操作
strcpy(addr,"hell world");   //往映射内存写东西
sleep(10);
shmdt(addr);              //取消对共享内存的链接
shmctl(shmID,IPC_RMID,0);   //卸载共享内存,0表示对卸载时候返回的参数不关心
return 0;
}**

读共享内存里的内容:

**#include <sys/shm.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include<string.h>
int main(){
key_t key;
key=ftok(".",1);          //获得key值
char* addr;                 //指向映射共享内存的指针
int shmID;
shmID=shmget(key,sizeof(4*1024),IPC_CREAT|0666 );
addr=shmat(shmID,0,0);  //两个0都指向系统默认操作
printf("%s",addr);   //从映射内存读东西

shmdt(addr);              //取消对共享内存的链接
shmctl(shmID,IPC_RMID,0);   //卸载共享内存,0表示对卸载时候返回的参数不关心
return 0;
}**

信号

信号的名字和编号 用shell命令:kill -l 查看

在这里插入图片描述

在这里插入图片描述
例子:想要杀一个进程 如a.out 那就要调用SIGKILL 对应编号为9
首先使用 ps -aux|grep a.out 查看 进程的pid号。
kill -9 pid号 就成功给a.out进程发送了死亡信号。

信号相关的API:

signal函数
typedef void (*sighandler_t)(int);

   sighandler_t signal(int signum, sighandler_t handler);

第一个参数:信号的编号
第二个参数 :信号的处理函数

作用:接收到对应编号的信号后,用信号处理函数做事情。

kill函数(给指定进程发送信号)
#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid, int sig);

参数:
pid:可能选择有以下四种

  1. pid大于零时,pid是信号欲送往的进程的标识。
  2. pid等于零时,信号将送往所有与调用kill()的那个进程属同一个使用组的进程。
  3. pid等于-1时,信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。
  4. pid小于-1时,信号将送往以-pid为组标识的进程。

sig:准备发送的信号代码,假如其值为零则没有任何信号送出,但是系统会执行错误检查,通常会利用sig值为零来检验某个进程是否仍在执行。

返回值说明: 成功执行时,返回0。失败返回-1,errno被设为以下的某个值 EINVAL:指定的信号码无效(参数 sig 不合法) EPERM;权限不够无法传送信号给指定进程 ESRCH:参数 pid 所指定的进程或进程组不存在。

接收信号携带的消息

sigaction函数
https://blog.csdn.net/weibo1230123/article/details/81411827
这位老哥写的很不错。借鉴借鉴。

函数原型:

 **#include <signal.h>
       int sigaction(int signum, const struct sigaction *act,
                     struct sigaction *oldact);**

第二个参数:处理信号函数的指针
第三个参数:拷贝 一般用NULL

重点是第二个参数
*const struct sigaction act

这是第二个参数结构体原型

 **struct sigaction {
               void     (*sa_handler)(int);
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };**

要收到信号带的参数,主要是第二个和第四个元素
第二个元素为处理信号函数
第四个元素要为SA_SIGINFO

处理函数原型 void (*sa_sigaction)(int, siginfo_t *, void *);

第一个参数 信号编号 第二个参数 信号所带来的信息(是一个结构体) 第三个参数处理函数内容

第二个参数有这些内容:

 **siginfo_t {
               int      si_signo;     /* Signal number */
               int      si_errno;    /* An errno value */
               int      si_code;     /* Signal code */
               int      si_trapno;   /* Trap number that caused
                                        hardware-generated signal
                                        (unused on most architectures) */
               pid_t    si_pid;      /* Sending process ID */
               uid_t    si_uid;      /* Real user ID of sending process */
               int      si_status;   /* Exit value or signal */
               clock_t  si_utime;    /* User time consumed */
               clock_t  si_stime;    /* System time consumed */
               sigval_t si_value;    /* Signal value */
               int      si_int;      /* POSIX.1b signal */
               void    *si_ptr;      /* POSIX.1b signal */
               int      si_overrun;  /* Timer overrun count; POSIX.1b timers */
               int      si_timerid;  /* Timer ID; POSIX.1b timers */
               void    *si_addr;     /* Memory location which caused fault */
               long     si_band;     /* Band event (was int in
                                        glibc 2.3.2 and earlier) */
               int      si_fd;       /* File descriptor */
               short    si_addr_lsb; /* Least significant bit of address
                                        (since kernel 2.6.32) */
           }**




例子:
在这里插入图片描述

发送带有消息的信号

sigqueue函数原型

#include <signal.h>

int sigqueue(pid_t pid, int sig, const union sigval value);

主要是第三个参数:
一个联合体:
union sigval {
int sival_int;
void *sival_ptr;
};
发送信号所携带的消息,有整型,也有字符型

例子:

#include<stdio.h>
#include <signal.h>
// int sigqueue(pid_t pid, int sig, const union sigval value);

#include <sys/types.h>
#include <unistd.h>

int main(int argc,char**argv){
        int signum;
        int  pid;
        union sigval value;
        value.sival_int=100;


        signum=atoi(argv[1]); // xian shu ru signum;
        pid=atoi(argv[2]);     // di er ge shu ru pid 

        sigqueue(pid,signum,value); // fa song pid signum dou wei ziji shu ru de xinhao qi zhong xinhao limian de zhi wei value ,value you tong guo union sigval value fuzhi
        printf("dang qian jin chen PID=%d",getpid());
        printf("fa song xin hao chengong \n\n\n\n");
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值