进程间通信————信号通信,共享内存,IPC对象之信号量集

进程间通信 ===》信号通信

应用:异步通信。 中断,

   1~64;32应用编程。(查表即可)


  如何响应:
Term   Default action is to terminate the process

Ign    Default action is to ignore the signal.
 wait
       

Core   Default action is to  terminate  the  process  and  dump  core  (see   core(5)).

程序会关闭,同时保存一个文件core,

使用 gdb a.out -c core  使程序直接到达错误位置。
       

Stop   Default action is to stop the process. 使进程暂停

 Cont   Default  action  is  to  continue  the  process  if  it is currently stopped 进程继续.

    
    kill      -xx     xxxx
    发送进程  信号    接收进程
    kill -9 1000
    a.out  9 1000

 

   1、发送端
 

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

 int kill(pid_t pid, int sig);

功能:通过该函数可以给pid进程发送信号为sig的系统信号。
参数:pid 要接收信号的进程pid
          sig 当前程序要发送的信号编号 i   <===  kill  -l
返回值:成功 0
             失败  -1;

echo $$当前进程的pid号

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    printf("input pid");
    char buf[10]={0};
    fgets(buf,sizeof(buf),stdin);// 1000\n
    pid_t pid = atoi(buf);
    int ret = kill(pid,9);
    if(-1 == ret)
    {
        perror("kill");
        exit(1);
    }
    return 0;
}

int raise(int sig)== kill(getpid(),int sig);

功能:给进程自己发送sig信号

unsigned int alarm(unsigned int seconds);SIGALAM
 功能:定时由系统给当前进程发送信号
            也称为闹钟函数

          闹钟只有一个,定时只有一次有效,
          但是必须根据代码逻辑是否执行判断。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    alarm(5);
    while(1)
    {
        printf("i'm working\n");
        sleep(1);
    }
    return 0;
}


int pause(void);

 功能:进程暂停,不再继续执行,除非
          收到其他信号。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int i = 0 ;
    while(1)
    {
        printf("i'm working\n");
        sleep(1);
        i++;
        if(5 == i)
        {
        
            pause();
        }
    }
    return 0;
}


2、信号  kill  -l  ==>前32个有具体含义的信号
        

SIGHUP (1): 挂起信号
SIGINT (2): 中断信号
SIGQUIT (3): 退出信号
SIGILL (4): 非法指令信号
SIGTRAP (5): 跟踪/断点陷阱信号
SIGABRT (6): 中止信号
SIGBUS (7): 总线错误信号
SIGFPE (8): 浮点异常信号
SIGKILL (9): 强制杀死进程信号
SIGUSR1 (10): 用户自定义信号 1
SIGSEGV (11): 段错误信号
SIGUSR2 (12): 用户自定义信号 2
SIGPIPE (13): 管道破裂信号
SIGALRM (14): 超时信号
SIGTERM (15): 终止信号
SIGSTKFLT (16): 协程栈错误信号
SIGCHLD (17): 子进程状态改变信号( 回收子进程)
SIGCONT (18): 继续执行信号
SIGSTOP (19): 停止进程信号
SIGTSTP (20): 终端停止信号
SIGTTIN (21): 后台进程尝试读取控制终端
SIGTTOU (22): 后台进程尝试写入控制终端
SIGURG (23): 紧急情况信号
SIGXCPU (24): 超过CPU时间限制信号
SIGXFSZ (25): 超过文件大小限制信号
SIGVTALRM (26): 虚拟定时器信号
SIGPROF (27): 用于分析的定时器信号
SIGWINCH (28): 窗口大小改变信号
SIGIO (29): 异步I/O事件通知信号
SIGPWR (30): 电源故障信号
SIGSYS (31): 非法系统调用信号


    3、接收端
      

     每个进程都会对信号作出默认响应,但不是唯一响应。
        一般如下三种处理方式:
        1、默认处理
        2、忽略处理 9,19
        3、自定义处理 9,19 捕获

      9  19 不能被忽略也不能被自定义      

 以上三种方式的处理需要在如下函数上实现。

    信号注册函数原型:
     
     void ( *signal(int signum, void (*handler)(int)) ) (int);


     typedef void (*sighandler_t)(int);
     ===》void (*xx)(int); == void fun(int);
     ===》xx是 void fun(int) 类型函数的函数指针
     ===》typedef void(*xx)(int)   sighandler_t; ///错误
          typedef int   myint;

     ===>sighandler_t signal(int signum, sighandler_t handler);
     ===> signal(int sig, sighandler_t fun);
     ===> signal(int sig, xxx fun);
     ===>fun 有三个宏表示:SIG_DFL 表示默认处理
                                             SIG_IGN 表示忽略处理
                                             fun     表示自定义处理

    练习:
        编写信号注册函数,并测试所有的32个系统信号
        是否能全部被忽略? 如果不能,则找出信号编号。

    结论: 9  19 不能被忽略也不能被自定义

示例1:

下面代码中使用signal函数,使运行5次结束,在另一个终端 发送继续的信号,程序就继续运行

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void myhandle(int num)
{
}

int main(int argc, char *argv[])
{
    int i = 0 ;
    signal(SIGCONT,myhandle);
    while(1)
    {
        printf("i'm working pid:%d\n",getpid());
        sleep(1);
        i++;
        if(5 == i)
        {
            pause();
        }
    }
    return 0;
}

示例2:

闹钟定时五i次后,运行进入到handle里面改变flag的值,使程序输出想要输出的另一个数据:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
int flag = 0;
void handle(int num)
{
    flag = 1;    
}
int main(int argc, char *argv[])
{
    signal(SIGALRM,handle);
    alarm(5);
    while(1)
    {
        if(0 == flag)
        {
        
            printf("i'm working\n");
        }
        else
        {
            
            printf("i'm reseting\n");
        }
        sleep(1);
    }
    return 0;
}

 

自定义信号处理:


    1、必须事先定义自定义函数,必须是如下格式:
        void fun(int sig)  sig 接收到的信息编号
        {

        }

    2、在所有的信号中有如下两个特列:
        10 SIGUSR1
        12 SIGUSR2
        
        专门预留给程序员使用的未定义信号。

示例3:


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void handle1(int num)
{
    static int i = 0;
    printf("老爸叫你\n");
    i++;
    if(3 == i )
    {
        signal(SIGUSR1,SIG_IGN);
    }

}
void handle2(int num)
{
    static int i = 0 ;
    printf("老妈叫你\n");
    i++;
    if(4== i)
    {
        signal(SIGUSR2,SIG_DFL);
    }
}
int main(int argc, char *argv[])
{
    signal(SIGUSR1,handle1);
    signal(SIGUSR2,handle2);
    while(1)    
    {
        printf("i'm playing pid :%d\n",getpid());
        sleep(1);
    }
    return 0;
}

  

    system v :  共享内存  信号量集

 shm,sem,msg

   IPC对象操作通用框架:
    0x  ftok
    key值 ==> 申请 ==》读写 ==》关闭 ==》卸载


    key值:===》唯一键值
    创建方式有三种:

    1、IPC_PRIVATE 固定的私有键值,其值等于 0x0
        一般用于有亲缘关系的进程间使用。

    2、ftok()创建临时键值。
    #include <sys/types.h>
    #include <sys/ipc.h>
                "/etc"                        '!'
    key_t ftok(const char *pathname, int proj_id);
    

功能:通过该函数可以将pathname指定的路径用来以
          proj_id生成唯一的临时键值。

参数:pathname 路径+名称===》任意文件,只要不会
           被删除重建即可。
          proj_id  整形的数字,一般用ASCII码的单字符
          表示与参数1的运算

 返回值:成功 返回唯一键值
               失败  -1;

   

用ipcs删除共享内存    

    ipcs -a 查询共享内存,信号量集,消息队列
    ipcrm -s 删除信号量集
          -m 删除共享内存
    共享内存 ===》效率最高的进程间通信方式

  

 操作流程:
     key ==》申请对象 ==》映射对象==》读写对象
         ==》撤销映射 ==》删除对象
        

    1、申请对象:shmget()
    #include <sys/ipc.h>
    #include <sys/shm.h>
    ps aux|grep a.out
        share memory get                 IPC_CREAT|0666
    int shmget(key_t key, size_t size, int shmflg)

 功能:使用唯一键值key向内核提出共享内存使用申请
    

参数:key  唯一键值
          size  要申请的共享内存大小
          shmflg 申请的共享内存访问权限,八进制表示
          如果是第一个申请,则用IPC_CREAT
          如果要检测是否存在,用IPC_EXCL
    

返回值:成功 返回共享内存id,一般用shmid表示
            失败  -1;

            share memory attach
    映射对象:shmat()
 void *shmat(int shmid, const void *shmaddr, int shmflg);

功能:将指定shmid对应的共享内存映射到本地内存。

参数:shmid 要映射的本地内存
          shmaddr 本地可用的地址,如果不确定则用NULL,表示
                  由系统自动分配。
          shmflg  
          0,表示读写
          SHM_RDONLY,只读
    返回值:成功 返回映射的地址,一般等于shmaddr
            失败 (void*)-1


    读写共享内存:类似堆区内存的直接读写:
    char * p ;
    
    write(fd,p,);
    read(fd,p,1024);
    memcpy(p,buf,1024);strcpy();
    memset(p,0,1024);== bzero(p,1024);
    memcmp(p,buf,1024); strcmp(a,b);
    
    
    
    字符串:     strcpy(p,"hello");
    字符/数字: 直接赋值

    练习:
        使用共享内存完成两个进程间的进程间通信,
        可以共享一个数字给对方。

    1、共享内存数据的存储方式是拷贝还是剪切?
        拷贝

    2、共享内存的数据如果多次不同进程读写会怎么样?
        同一操作对象,数据没有偏移情况下会覆盖。

    撤销映射:shmdt
    int shmdt(const void *shmaddr);

功能:将本地内存与共享内存断开映射关系。

参数:shmaddr 要断开的映射地址。

返回值:成功  0
            失败  -1;


    删除对象:shmctl
    int shmctl(int shmid, int cmd, struct shmid_ds *buf);

功能:修改共享内存属性,也可以删除指定的共享内存对象。

 参数:shmid 要删除的共享内存对象
            cmd IPC_RMID 删除对象的宏
           buff NULL 表示只删除对象。

返回值:成功 0
            失败 -1

    以上共享内存可能存在如下问题:
    进程1 写入共享内存,如何通知进程2 读共享内存。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main(int argc, char *argv[])
{
    key_t key = ftok("./",'!');    
    if(-1 == key)
    {
        perror("ftok");
        exit(1);
    }
    printf("key is 0x%x\n",key);

    int shmid = shmget(key,4096,IPC_CREAT|0666);
    if(-1 == shmid)
    {
        perror("shmget");
        exit(1);
    }

    void* p =  shmat(shmid,NULL,!SHM_RDONLY);
    if((void *) -1 == p )
    {
        perror("shmat");
        exit(1);
    }

    strcpy((char*)p,"hello,this is shm test");

    shmdt(p);
    return 0;
}

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main(int argc, char *argv[])
{
    key_t key = ftok("./",'!');    
    if(-1 == key)
    {
        perror("ftok");
        exit(1);
    }
    printf("key is 0x%x\n",key);

    int shmid = shmget(key,4096,IPC_CREAT|0666);
    if(-1 == shmid)
    {
        perror("shmget");
        exit(1);
    }

    void* p =  shmat(shmid,NULL,!SHM_RDONLY);
    if((void *) -1 == p )
    {
        perror("shmat");
        exit(1);
    }

   // strcpy((char*)p,"hello,this is shm test");
   printf("mem is %s\n",(char*)p);
    shmdt(p);
    //shmctl(shmid,IPC_RMID,NULL);
    return 0;
}


    IPC对象之信号量集 ==>sem ===》

为了解决共享内存的临界资源访问

 

   操作流程:
        key ==> 申请信号量集 ==》init==>PV操作 ===》删除信号量

        semaphore
    1、申请信号量  semget()
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>

    int semget(key_t key, int nsems, int semflg);
    功能:通过唯一键值向内核提出信号量申请。
    参数:key 唯一键值
          nsems 要申请的信号量个数
          semflg 申请的信号量的访问权限
    返回值:semid.
            失败 -1;

    2、pv操作;semop

    p ==>sem_wait() ==>sem = sem-1;
    v ==>sem_post() ==>sem = sem+1;

    int semop(int semid, struct sembuf *sops, unsigned nsops);
    功能:修改指定信号量集中信号量的值。
    参数:semid 信号量集id
          sops ==》结构体如下:
          struct sembuf
          {
              unsigned short sem_num;  ///信号量集中信号量的编号,默认以0开始
              short             sem_op;   ///信号量的PV操作,如果改值等于-1则表示p        
                                                                  等于1 则表示v
                                                                  等于0 则表示阻塞

              short          sem_flg;   ///信号量的操作方式 0 表示默认阻塞。
              IPC_NOWAIT and SEM_UNDO.
          };
          nsops 信号量的设置值个数。
    返回值:成功 0
            失败 -1

    通常会将以上函数做如下自定义封装:

    int my_sem_wait(int id,int sem)
    {
        struct sembuf mysem;
        mysem.sem_num = sem;
        mysem.sem_op  = -1;
        mysem.flg      = 0;

        if(semop(id,&mysem,1) < 0)
            return -1;
        else
            return 0;
    }

    int my_sem_post(int id,int sem)
    {
        struct sembuf mysem;
        mysem.sem_num = sem;
        mysem.sem_op  = 1;
        mysem.flg      = 0;

        if(semop(id,&mysem,1) < 0)
            return -1;
        else
            return 0;
    }

    3、信号量的删除
     int semctl(int semid, int semnum, int cmd, ...);
     功能:根据semid删除指定的信号量集
     参数:semid 要删除的信号量集
           semnum 要删除的信号量集中的信号量的编号
           cmd IPC_RMID 删除对象宏
           ...  可变长参数可以不写
    返回值:成功 0
            失败 -1;

    =====================================================

    练习:
        设计两个进程,完成如下功能:
        进程1 获取用户输入的信息并写入共享内存
        进程2 获取共享内存信息并将其打印输出同时写文件
        双方遇到 "exit" 退出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/768627.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mysql 忘记 root 密码的解决办法(针对不同 mysql 版本)

文章目录 1.前提说明1.1 cmd 窗口打开方式1.2 mysql 服务相关命令知识补充1.3 三个 mysql 版本说明1.4 运行时可能发生的报错问题&#x1f340; 跳过密码授权命令报错&#x1f340; 修改密码时报错&#x1f340; ERROR 2003 (HY000): Cant connect to MySQL server on localhos…

订单服务-提交订单业务立即购买业务

文章目录 1、提交订单 业务2、在 OrderController 创建 submitOrder 方法3、 在 OrderServiceImpl 中实现 submitOrder 方法4、根据id查询sku详情&#xff08;service-product"&#xff09;5、查询用户地址保存到订单项中&#xff08;service-user&#xff09;6、删除购物…

vue3开发过程中遇到的一些问题记录

问题&#xff1a; vue3在使用 defineProps、defineEmits、defineExpose 时不需要import&#xff0c;但是 eslint会报错error defineProps is not defined no-undef 解决方法&#xff1a; 安装 vue-eslint-parser 插件&#xff0c;在 .eslintrc.js 文件中添加配置 parser: vue-e…

论文学习_UVSCAN: Detecting Third-Party Component Usage Violations in IoT Firmware

论文名称发表时间发表期刊期刊等级研究单位 Understanding the Security Risks Introduced by Third-Party Components in IoT Firmware 2024年IEEE TDSCCCF A佐治亚理工学院 1. 引言 研究背景&#xff1a;物联网&#xff08;IoT&#xff09;已经无处不在&#xff0c;为我们…

DGMamba: Domain Generalization via Generalized State Space Model论文笔记

文章目录 DGMamba: Domain Generalization via Generalized State Space Model摘要动机DGMamba设计隐藏状态抑制(HSS)语义感知补丁细化(SPR)免先验扫描域上下文交换上下文patch识别 实验结果 DGMamba: Domain Generalization via Generalized State Space Model paper: https:/…

基于Cardinal的AWD攻防平台搭建与使用以及基于docker的题目环境部署

关于 CTF 靶场的搭建与完善勇师傅前面已经总结过了&#xff0c;参考&#xff1a; CTF靶场搭建及Web赛题制作与终端docker环境部署_ctfoj搭建-CSDN博客 基于H1ve一分钟搭好CTF靶场-CSDN博客 Nginx首页修改及使用Nginx实现端口转发_nginx 修改欢迎首页-CSDN博客 关于H1ve导…

Winform使用HttpClient调用WebApi的基本用法

Winform程序调用WebApi的方式有很多&#xff0c;本文学习并记录采用HttpClient调用基于GET、POST请求的WebApi的基本方式。WebApi使用之前编写的检索环境检测数据的接口&#xff0c;如下图所示。 调用基于GET请求的无参数WebApi 创建HttpClient实例后调用GetStringAsync函数获…

2.4 C#开发环境 xml格式保存参数----范例实现

2.4C#开发环境 xml格式保存参数----范例实现 1 程序参数保存目录层次说明 1 选择程序号| 相机号|窗口号 2 导入参数&#xff1a;就会从本地目录读取参数&#xff0c;并且显示图片和ROI 3 保存参数&#xff1a;把当前控件图片和ROI信息保存到指定程序号|相机号|窗口号中 2 参数…

剪映数字人口播原理终于搞清楚了

剪映版本升级了,新版本支持数字人定制,于是我赶紧申请了使用资格 目前的价格是49元单个价格/30天 支付49元之后剪映要求上传2.5至10分钟的视频 接着要阅读一段话并录制视频上传 第三步提交,提交完成之后大概两三个小时就会有一个特定数字人形象出现:

不只是咨询,更是转型加速器——精益生产咨询!

以前咱们说精益生产&#xff0c;总觉得是套现成的模板&#xff0c;每家企业都得照葫芦画瓢。但现在不一样了&#xff0c;精益生产咨询就像是个高级定制师&#xff0c;它深入了解你的企业现状、行业特点、市场趋势&#xff0c;然后给你量身打造一套专属的精益转型方案。这种既接…

java内存管理机制详解之运行时数据区

正文 C与java之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”&#xff0c;墙外的人想进去&#xff0c;墙里的人却想出来…… 与C、C程序员时刻要关注着内存的分配与释放&#xff0c;会不会又有哪里出现了内存泄露不同是&#xff0c;java程序员可以“高枕无忧”。因为…

Visual Studio 中的键盘快捷方式

1. Visual Studio 中的键盘快捷方式 1.1. 可打印快捷方式备忘单 1.2. Visual Studio 的常用键盘快捷方式 本部分中的所有快捷方式都将全局应用&#xff08;除非另有指定&#xff09;。 “全局”上下文表示该快捷方式适用于 Visual Studio 中的任何工具窗口。 生成&#xff1…

【C语言】指针经典例题

题1&#xff1a; #include <stdio.h>int main() {int a[5] { 1, 2, 3, 4, 5 };int* ptr (int*)(&a 1);printf("%d,%d", *(a 1), *(ptr - 1));return 0; } //程序的结果是什么&#xff1f; 解答如下&#xff1a; 题2&#xff1a; #include <std…

Access数据操作

Access Access 作为 Office的组件之一&#xff0c;在很多 Excel难以施展其能力的场所&#xff0c;也能轻松应对。同为Office组件之一的Excel具有灵活的数据处理和分析能力&#xff0c;然而&#xff0c;其能力是有局限的&#xff0c; 比如当涉及两个数据表之间的“关联”操作时&…

【分布式数据仓库Hive】HivQL的使用

目录 一、Hive的基本操作 1. 使用Hive创建数据库test 2. 检索数据库&#xff08;模糊查看&#xff09;&#xff0c;检索形如’te*’的数据库 3. 查看数据库test详情 4. 删除数据库test 5. 创建一个学生数据库Stus&#xff0c;在其中创建一个内部表Student&#xff0c;表格…

快速下载!Windows 7旗舰版系统:集成所有补丁!

微软对Windows7系统停止支持后&#xff0c;Windows7设备不再收到安全补丁程序、修补程序。尽管如此&#xff0c;许多用户仍然认为Windows7是最好用、最经典的系统。有用户就特别喜欢Windows7旗舰版系统&#xff0c;那么接下来系统之家小编为大家带来的全补丁版本的Windows7系统…

互联网应用主流框架整合之SpringCloud微服务治理

微服务架构理念 关于微服务的概念、理念及设计相关内容,并没有特别严格的边界和定义,某种意义上说,适合的就是最好的,在之前的文章中有过详细的阐述,微服务[v1.0.0][Spring生态概述]、微服务[设计与运行]、微服务[v1.0.0][服务调用]、微服务[开发生命周期]、微服务[面临的…

LLM应用:传统NLP任务

LLM出来以后&#xff0c;知乎上就出现了“传统NLP已死”的言论&#xff0c;但是传统NLP真的就被扔进历史的垃圾桶了吗&#xff1f; 其实&#xff0c;尽管LLM具有出色的通用能力&#xff0c;但仍然无法有效应对低资源领域的自然语言处理任务&#xff0c;如小语种翻译。为了更好地…

springboot+vue+mybatis前台点菜系统+PPT+论文+讲解+售后

21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存储达到…