笔记整理—linux进程部分(6)进程间通信、alarm和pause

news/2024/10/3 13:21:42 标签: 笔记, linux, 嵌入式硬件, arm, c语言, 运维

        两个进程间通信可能是任何两个进程间的通信(IPC)。同一个进程是在同一块地址空间中的,在不同的函数与文件以变量进程传递,也可通过形参传递。2个不同进程处于不同的地址空间,要互相通信有难度(内存隔离的原因)本质上也是为了安全。

        多数情况下是不会使用进程间通信的,大部分都是单进程,多线程只有在设计复杂的大型程序时候才会去使用IPC(如GUI或服务器)。IPC在中小程序上是用不上的。

        linux提供四类进程间通信的方法,①管道,有名管道、无名管道。②system V IPC信号量、消息队列、共享内存。③socket套接字(一般用于网络通信)。④信号。

        进程间通信IPC不常用的问题:①日常用的少,大程序才用得上。②很复杂,是linux应用编程中难度极大的部分。③细节很多。④初学困难。

        管道:只允许读一次,一般情况下所说的管道是无名管道,若使用有名管道一般称为FIFO。无名管道通信原理,内核维护的一块内存,有读/写端。

        管道是单向通信的,半双工的,但是一般被视为单工通信。单工通信,从左到右,单向运动。半双工,同一时间内从左到右,下一时刻能从右往左。全双工,同时支持双向运动。

        为什么一般要把管道通信做成单工通信呢,其原因是,在双方都有读写的情况下进程A可能会把自己写的读写读走,让B进程没地方读信息,所以一般情况下,管道通信做的都是单工通信,本质上就是因为公共区域没区分,会发生抢读。所以就可以把这半双工通信作如下的操作:

        无名管道通信,只能在父子之间进行通信父进程先创建pipe的带两个文件fd,pipe fd[2]。父进程fork子进程基础fd,父进程关闭读(或写),子进程关闭写(读)。只能在父子之间通信,这些缺点被有名管道进行修复。

        

        有名管道,也是内核维护的一块内存,表现为一个有名字的文件,用两个进程去mkfifo创建fifo文件,通过open打开达到fd,进行通信,不要求目标为父子进程,因为这里有真实的文件存在。

        

        system V IPC其有专用的API进程实现。分为三种方法,信号量,消息队列,共享内存。实际上用的也是内核提供的公共内存。

        消息队列本质上是一个队列FIFO,内核内部维护一个FIFO,工作时A可以从队列中放东西,B从队列中读东西。

        信号量,实质是一个计数器,一个计数的变量,主要用于互斥与同步(进程间互斥与资源同步等),就一个flag,可以做锁。

        共享内存,内核中用一片内存,这块区域可以共同使用。

        大片内存共享:A(摄像头)———>B(视频编码)———>C(视频传输)

        方法①:A得到一个图像信息,复制给B一份,B去处理。

        方法②:A和B用同一块内存空间共同处理图像。

        实例就是LCD映射,LCD显存与代码共享一个内存空间存放图像。

        共享内存适合进行大信息处理。

        

        信号通信方式,是一种内容收到限制的异步通信机制。用于进程间通信或进程与内核通信;通信内容受到限制,只是一个信号;信号是异步的,不在同一个时钟,信号具有滞后性,同样和中断一样有不可预知性。信号的本质就是一个数字。

        信号由谁处理——>进程。处理的方式有三种①忽略信号。②驳货信号(信号绑定了一个函数)。③默认处理,忽略或终止进程。不去主动的明确忽略信号,捕获信号,则会默认处理信号。

        常见的信号有:

SIGINT    值为2    作用为ctrl+c时OS送给前台进程组中每个进程。
SIGPOLL/SIGIO    值为8    提示一个异步IO事件
SIGKILL    值为9    杀死进程的最终方法(不可忽略)
SIGALARM    值为14    与alarm闹钟相关
SIGCHLD    值为17    子进程停止或终止时OS向父进程发送,如wait()等待收尸

        进程处理信号的方式:

sighandler_t signal(int signum, sighandler_t handler);

sighandler_t handler就是处理的方法相当于中断里面的处理函数,信号与槽里面的槽函数

typedef void (*sighandler_t)(int);

        处理SIGINT信号默认终止进程(异常退出)

typedef void (*sighandler_t)(int);

void func(int sig)
{
    printf("signal:%d\n",sig);
}

int mian(void)
{
    signal(SIGINT,func);//主动捕获,默认终止进程
    while(1);
}

signal()返回值①返回正确的处理方法(成功)
             ②返回errnuber(SIG_ERR失败)

        SIG_ERR是一个函数指针,signal返回无论正确与否都返回一个函数指针。SIG_ERR值为强制转换的-1表示err;SIG_DFL值为强制转换的0表示默认;SIG)IGN值为强制转换的1表示忽略。

        signal(SIGINT,SIG_DFL)指定SIGINT为默认处理;signal(SIGINT,SIG_IGN)指定SIGINT为忽略处理。但是当使用signal()去绑定处理函数时可能会出现因为版本问题的错误。可以使用:

 int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

        可以保证signal的其移植性。

 struct sigaction {
               void     (*sa_handler)(int);//signal中的方法
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };
通过传递NULL可以返回旧的处理方法

        alarm函数,闹钟——到店了应该干什么。

unsigned int alarm(unsigned int seconds);

        时间到了,返回一个SIGALRM信号,若传一个0,会取消之前没执行完的闹钟,在一个闹钟没完成时,会返回剩余时间。

typedef void (*sighandler_t)(int);

void func(int sig)
{
    printf("signal:%d\n",sig);
}

int main()
{
    unsigned int ret=-1;
    signal(SIGALRM,func);
    ret=alarm(3);
    while(1);
}

        struct sigaction act={0};act.sa_handler=func;sigaction(SIGALRM,&act,NULL);对上面进行替换。

typedef void (*sighandler_t)(int);

void func(int sig)
{
    printf("signal:%d\n",sig);
}

int main()
{
    unsigned int ret=-1;
    struct sigaction act={0};
    act.sa_handler=func;
    sigaction(SIGALRM,&act,NULL);
    ret=alarm(3);
    while(1);
}

        内核只给一个进程提供一个alarm时钟,只能定一个闹钟,一个没结束再次调用将会返回上一个闹钟还剩余的时间,覆盖闹钟重新计时。

        pause函数,使进程挂起,让进程暂停运行,交出cpu,利用该函数使进程卡住,要退出该函数需要信号进行输入,进程被唤醒。所以可以使用alarm与pause模拟sleep()。

typedef void (*sighandler_t)(int);

void func(int sig)
{
}

void my_sleep(unsigned int seconds)
{
    struct sigaction act={0};
    act.sa_handler=func;
    sigaction(SIGALRM,&act,NULL);
    alarm(seconds);
    pause();
}

int main()
{
    my_sleep(1);
    printf("hi\n");
    my_sleep(4);
    printf("I am\n");
    my_sleep(3);
    printf("jack\n");
    return 0;
}


http://www.niftyadmin.cn/n/5688448.html

相关文章

Jenkins pipeline配置示例

前提条件&#xff1a;已经安装Jenkins并能正常启动 如果Jenkins安装启动遇到问题可以参考&#xff1a; 1.创建pipeline 点击新建项目&#xff1a; 输入名称&#xff0c;选择pipeline&#xff1a; 进入配置页面&#xff0c;如果要配置GitHub Webhook要勾选&#xff1a;<fo…

Flume面试整理-Flume是什么?

Apache Flume 是一个分布式的、可靠的、高可用的数据收集和传输系统,专为从各种数据源(如日志文件、网络流)收集、聚合和传输大量数据而设计。它主要用于在大数据生态系统中,特别是Hadoop环境中,将数据从多个分散的来源实时地传输到一个集中的存储系统(如HDFS、HBase等)…

用户登录与信息管理:实现小程序登录与用户信息存储

用户登录与信息管理&#xff1a;实现小程序登录与用户信息存储 在现代的移动应用中&#xff0c;用户登录与信息管理是构建个性化用户体验的基础。小程序作为轻量级的应用形式&#xff0c;在简化开发流程的同时&#xff0c;也需要我们妥善管理用户的登录状态与用户信息。本文将…

React生命周期以及Hook

React生命周期可概括为以下关键阶段&#xff08;针对类组件&#xff0c;函数组件主要通过Hooks实现类似功能&#xff09;&#xff1a; 挂载&#xff08;Mounting&#xff09;&#xff1a; constructor&#xff1a;初始化state和绑定事件处理函数。 render&#xff1a;返回组件的…

【AI驱动TDSQL-C Serverless 数据库技术实战营】基于Langchain的电商可视化分析

人工智能技术的飞速发展已深刻影响电商行业&#xff0c;显著提升了个性化推荐、用户行为分析、库存管理和市场预测等领域的效率。构建一个高效的AI驱动电商数据分析平台已成为行业的核心需求。本文里&#xff0c;我们将使用腾讯云的高性能应用平台 HAI&#xff08;专为AI和科学…

深化专业,广纳技能,构建软实力

一、引言 ----  随着人工智能&#xff08;AI&#xff09;和生成式人工智能&#xff08;AIGC&#xff09;如ChatGPT、Midjourney、Claude等大语言模型的持续涌现&#xff0c;AI辅助编程工具日益普及&#xff0c;程序员的工作方式正在经历深刻的变革。这种变革既带来了对部分编…

解决OpenCV保存视频 视频全部为绿色的bug

目录 项目场景&#xff1a; 问题描述 原因分析&#xff1a; 解决方案&#xff1a; 项目场景&#xff1a; 使用OpenCV-Python 保存视频&#xff0c;视频为numpy array格式&#xff0c;保存的视频全部为无意义的绿色。 问题描述 用opencv 保存的视频会出现全部为绿色的情况&…

企业级Kubernetes部署

华子目录 k8s中容器的管理方式k8s集群部署安装k8s部署工具部署软件仓库&#xff0c;添加k8s源设置kubectl命令补全功能 k8s集群中安装cri-dockerk8s集群中启动cri-docker服务在k8s-master上拉取k8s所需镜像并上传到harbor上修改cri-docker.service文件k8s集群中启动kubeletk8s集…