C/C++进程超详细详解【下部分】(系统性学习day8)

目录

前言

一,有名管道通信

1 .概念

2 .创建有名管道

实例代码如下:

二、信号通信

1 .概念

2 .用户进程对信号的响应方式

3. 用户进程对常用信号的缺省操作

4. 信号处理流程

5. 信号相关函数(系统调用)

 5.1 kill - 给指定进程发送信号

实例代码如下: 

5.2 raise() --给当前进程发送信号  

实例代码如下: 

5.3 alarm() 在进程中设置定时器(闹钟)  

实例代码如下: 

5.4 pause() 使进程挂起  

 实例代码如下:

5.5 signal 注册信号  

实例代码如下: 

总结


前言

上篇博客对C/C++进程的中部分进行了详细讲解,本篇博客将继续讲解和补充关于线程的知识点。


一,有名管道通信

1 .概念

1.由于无名管道只能用于具有亲缘关系的进程之间,这就限制了无名管道的使用范围。

2.而有名管道可以使互不相关的两个进程互相通信。有名管道可以通过路径名来指出,并且在文件系统中可见

3.进程通过文件IO来操作有名管道

2 .创建有名管道

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
//参数1 ---- 管道的名称
//参数2 ---- 管道的权限
//返回值 -----成功:0,失败:-1

例如:

int main(int argc ,char **argv)
    {

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

        //创建有名管道
        if(mkfifo(argv[1],0666) < 0){   //管道权限= 0666 & ~umusk
            perror("mkfifo");
            exit(1);
        }

        return 0;
    }

实例代码如下:

//从管道读10个整数,然后排序,并打印
int main(int argc ,char **argv)
{int fd;int a[10],i,j,flag;if(argc != 2){fprintf(stderr,"Usage: %s <fifoname>\n",argv[0]);exit(1);}//判断管道文件是否存在,如果不存在则创建,存在则直接打开if(access(argv[1],F_OK)){//创建有名管道if(mkfifo(argv[1],0666) < 0){   //管道权限= 0666 & ~umuskperror("mkfifo");exit(1);}}//打开管道if((fd = open(argv[1],O_RDWR)) < 0){perror("open");exit(1);}//从管道中读10个整数if(read(fd,a,sizeof(a)) < 0){perror("read");exit(1);}//排序for(i = 0; i < 9; i++){flag = 1;for(j = 0; j < 9-i; j++)if(a[j] > a[j+1]){a[j] = a[j] + a[j+1];a[j+1] = a[j] - a[j+1];a[j] = a[j] - a[j+1];flag = 0;}if(flag)break;}for(i = 0; i < 10; i++){printf("%d  ",a[i]);fflush(stdout);sleep(1);}printf("\n");close(fd);return 0;
}
//从键盘输入10个整数,并写入管道
int main(int argc ,char **argv)
{int fd;int a[10],i;if(argc != 2){fprintf(stderr,"Usage: %s <fifoname>\n",argv[0]);exit(1);}//判断管道文件是否存在,如果不存在则创建,存在则直接打开if(access(argv[1],F_OK)){//创建有名管道if(mkfifo(argv[1],0666) < 0){   //管道权限= 0666 & ~umuskperror("mkfifo");exit(1);}}//打开管道if((fd = open(argv[1],O_RDWR)) < 0){perror("open");exit(1);}//键盘输入10个整数printf("请输入10个整数:");for(i = 0; i < 10; i++){scanf("%d",&a[i]);}//向管道中写10个整数write(fd,a,sizeof(a));close(fd);return 0;
}

二、信号通信

1 .概念

信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式

信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。

如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程

2 .用户进程对信号的响应方式

(1)忽略信号:
    对信号不做任何处理,但是有两个信号不能忽略:即SIGKILL及SIGSTOP。
(2)捕捉信号:
    定义信号处理函数,当信号发生时,执行相应的处理函数。
(3)执行缺省操作:
    Linux对每种信号都规定了默认操作

//查看linux系统中的信号---kill
peter@ubuntu:~/2308/proc/day03_code$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

3. 用户进程对常用信号的缺省操作

信号名含义默认操作
SIGHUP

该信号在用户终端连接(正常或非正常)结束时发出,通常是在终端的控   

制进程结束时,通知同一会话内的各个作业与控制终端不再关联。            

终止
SIGINT该信号在用户键入INTR字符(通常是Ctrl-C)时发出,终端驱动程序发送                  
此信号并送到前台进程中的每一个进程。                
终止
SIGQUIT该信号和SIGINT类似,但由QUIT字符(通常是Ctrl-\)来控制。终止
SIGILL该信号在一个进程企图执行一条非法指令时(可执行文件本身出现错误,                     
或者试图执行数据段、堆栈溢出时)发出。    
终止
SIGFPE

该信号在发生致命的算术运算错误时发出。这里不仅包括浮点运算错误,                   

 还包括溢出及除数为0等其它所有的算术的错误。    

终止
SIGKILL该信号用来立即结束程序的运行,并且不能被阻塞、处理和忽略。终止
SIGALRM该信号当一个定时器到时的时候发出。终止
SIGSTOP该信号用于暂停一个进程,且不能被阻塞、处理或忽略。暂停进程
SIGTSTP该信号用于暂停交互进程,用户可键入SUSP字符(通常是Ctrl-Z)发出这个信号。暂停进程
SIGCHLD子进程改变状态时,父进程会收到这个信号忽略
SIGABORT该信号用于结束进程终止

4. 信号处理流程

 

5. 信号相关函数(系统调用)

 5.1 kill - 给指定进程发送信号

#include <sys/types.h>
    #include <signal.h>
    int kill(pid_t pid, int sig);
    //参数1  -----信号发送的目标进程的ID
                 参数1取值分四种
                 pid > 0 ,给进程号为pid的进程发送信号
                 pid = 0 , 给当前进程组中每一个进程发送信号
                 pid = -1, 发送给进程表中所有的进程
                 pid < -1, 给指定进程组中的每一个进程发送信号,该进程组的ID为-pid
    //参数2  -----要发送的信号
    //返回值----成功:0,失败:-1

实例代码如下: 
int main(int argc,char **argv)
{
#if 1pid_t pid;if(argc != 2){fprintf(stderr,"Usage: %s <pid>\n",argv[0]);exit(1);}pid = atoi(argv[1]);   //atoi将字符串转为整数if(kill(pid,SIGKILL) < 0){perror("kill");exit(1);}
#elsepid_t pid1,pid2;int i;if((pid1 = fork()) < 0){perror("fork");exit(1);}else if(!pid1){   //子进程1for(i = 0; ; i++){printf("pid = %d\n",getpid());sleep(1);}}else{if((pid2 = fork()) < 0){perror("fork");exit(1);}else if(!pid2){  //子进程2for(i = 0; ; i++){printf("pid = %d\n",getpid());sleep(1);}}else{  //父进程for(i = 0; ; i++){printf("pid = %d\n",getpid());sleep(1);if(i == 5)//kill(0,SIGKILL); //0--给进程组中每一个进程发送信号kill(pid2,SIGKILL);  //给pid2发送信号}}}#endifreturn 0;
}

5.2 raise() --给当前进程发送信号  

#include <signal.h>
int raise(int sig);
//参数 ----信号
//返回值----成功:0,失败:-1

实例代码如下: 
int main(void)
{int i;for(i = 0; ; i++){printf("pid = %d\n",getpid());sleep(1);if(i == 7)raise(SIGKILL);}return 0;
}

5.3 alarm() 在进程中设置定时器(闹钟)  

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
//参数 ---- 要定时的秒数
//返回值 ----如果第一次调用该函数,返回值为0,
            如果调用之前已经设置了定时器,则返回上次定时剩余的秒数

实例代码如下: 
int main(void)
{int i,ret;ret = alarm(20);  // 从该语句开始计时,7秒之后发送SIGALRM信号给当前进程printf("ret = %d\n",ret);for(i = 0; ; i++){printf("pid = %d,i = %d\n",getpid(),i);sleep(1);if(i == 7){ret = alarm(5);printf("ret = %d\n",ret);}}return 0;
}

5.4 pause() 使进程挂起  

int pause(void);
//使进程挂起 ,直到进程收到任意一个信号则返回。

 实例代码如下:
//信号处理函数
void fun(int signo)
{int i;for(i = 0; i < 3; i++){printf(GREEN "正在吃饭\n"NONE);sleep(1);}
}int main(void)
{int i,j;//注册信号SIGALRMsignal(SIGINT,fun);for(i = 0; ; i++){pause();  //使进程挂起,直到收到信号为止for(j = 0; j < 5; j++){printf("正在睡觉\n");sleep(1);}}return 0;
}

5.5 signal 注册信号  

#include <signal.h>
typedef void (*sighandler_t)(int);  //定义函数指针类型名称
sighandler_t signal(int signum, sighandler_t handler);
//参数1 ---- 要注册的信号
//参数2 ---- 信号的响应方式:
                SIG_IGN   ----- 忽略信号
                SIG_DFL   ----- 对信号进行缺省操作
        信号处理函数的指针    ----- 捕捉信号,当收到信号,则会执行信号处理函数
        void xxx_fun(int)
        {
        
        }
//返回值 ----成功:信号处理函数指针,失败:SIG_ERR

实例代码如下: 
//信号处理函数
void eat(int signo)
{int i;for(i = 0; i < 3; i++){printf(GREEN "正在吃饭\n"NONE);sleep(1);}
}int main(void)
{int i;//注册信号SIGALRMsignal(SIGALRM,eat);for(i = 0; ; i++){if(i % 8 == 0){alarm(8);  // 从该语句开始计时,7秒之后发送SIGALRM信号给当前进程printf("开始睡觉,设置闹钟\n");}printf("正在睡觉......\n");sleep(1);}return 0;
}


总结

        本篇文章针对进程进行最后的超详细讲解和补充,希望能够帮到大家!

        以后还会给大家展现更多关于嵌入式和C语言的其他重要的基础知识,感谢大家支持懒大王!

       希望这篇博客能给各位朋友们带来帮助,最后懒大王请来过的朋友们留下你们宝贵的三连以及关注,感谢你们!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gdb的使用

目录 gdb工具的使用 代码调试相关指令 运行程序指令 r 显示代码的指令 l 给代码打断点 b 查看断点位置 info b 执行代码到断点处停止 关闭断点 d断点编号 关闭某个断点&#xff0c;但不删除 disable编号 打开某个断点 enable断点编号 逐过程调试代码 n 逐语句调试代码 s 查看…

go-fastdfs分布式文件存储集群搭建和测试

一、官方文件 https://sjqzhang.github.io/go-fastdfs/#character2、集群原理 小集群原理&#xff1a; 大集群原理 二、服务端集群部署 1、在集群每个节点机器上下载安装包 (建议使用最新稳定版本&#xff09; wget --no-check-certificate https://github.com/sjqzhang/go…

专题一:递归【递归、搜索、回溯】

什么是递归 函数自己调用自己的情况。 为什么要用递归 主问题->子问题 子问题->子问题 宏观看待递归 不要在意细节展开图&#xff0c;把函数当成一个黑盒&#xff0c;相信这个黑盒一定能完成任务。 如何写好递归 一、汉诺塔 class Solution { public:void dfs(vec…

react项目从webpack迁移到vite的解决方案

虽然webpack是前端工程编译工具的王者&#xff0c;但是最近vite牛逼吹的震天响&#xff0c;说什么开发/生产打包速度甩webpack 100条街。不管是不是事实&#xff0c;总得尝试一下吧。 于是说干就干&#xff0c;在网上找了很多资料&#xff0c;终于搞定了&#xff0c;以下就是r…

QT4.8.7安装详细教程

QT4.8.7安装详细教程&#xff08;MinGW 4.8.2和QTCreator4.2.0&#xff09; 1.下载及安装2.配置环境 此文是在下方链接博文的基础上&#xff0c;按自己的理解整理的https://blog.csdn.net/xiaowanzi199009/article/details/104119265 1.下载及安装 这三个文件&#xff0c;顺序是…

更直观地学习 Git 命令

theme: condensed-night-purple 前言 本文参考于 Learn Git Branching 这个有趣的 Git 学习网站。 在该网站&#xff0c;可以使用 show command 命令展示所有可用命令。 你也可以直接访问网站的sandbox&#xff0c;自由发挥。 本地篇 基础篇 git commit git commit将暂…

MySQL学习笔记23

逻辑备份&#xff1a; 1、回顾什么是逻辑备份&#xff1f; 逻辑备份就是把数据库、数据表或者数据进行导出&#xff0c;导出到一个文本文件中。 2、逻辑备份工具&#xff1a; mysqldump&#xff1a;提供全库级、数据库级别以及表级别的数据备份。 mysqldumpbinlog&#xff…

苹果签名有多少种类之TF签名(TestFlight签名)是什么?优势是什么?什么场合需要应用到?

&#xff08;一&#xff09;TestFlight 能够让您&#xff1a;邀请内部和外部的测试人员为应用程序提供反馈。 跟踪应用程序在测试过程中发现的 bug 和用户体验问题。 收集 Crash 报告&#xff0c;了解应用程序在真实设备上的运行状况。 要使用 TestFlight&#xff0c;您可以按照…

[Spring] Spring5——AOP 简介

目录 一、AOP 简介 1、什么是 AOP 二、AOP 底层原理 1、动态代理原理 2、基于接口的 JDK 动态代理 3、基于继承的 CGLib 动态代理 三、底层原理实现—— JDK 动态代理 1、使用 Proxy 类的方法创建代理对象 2、JDK 动态代理示例 四、AOP 操作术语 1、连接点 2、切入…

docker安装apisix全教程包含windows和linux

docker安装apisix 一、Windows安装1、首先需要安装docker和docker compose&#xff0c;如果直接安装docker desktop&#xff0c;会自动安装docker compose。2、重新启动电脑3、访问 Docker 的下载&#xff08;[https://www.docker.com/products/docker-desktop](https://www.do…

Java类型转换和类型提升

目录 一、类型转换 1.1 自动类型转换&#xff08;隐式&#xff09; 1.1.1 int 与 long 之间 1.1.2 float 与 double 之间 1.1.3 int 与 byte 之间 1.2 强制类型转换&#xff08;显示&#xff09; 1.2.1 int 与 long 之间 1.2.2 float 与 double 之间 1.2.3 int 与 d…

【网络编程】UDP数据报套接字编程和TCP流套接字编程

文章目录 1. 网络编程基础1.1 为什么需要网络编程&#xff1f;1.2 网络编程是什么&#xff1f;1.3 概念 2. Socket套接字3. UDP数据报套接字编程3.1 DatagramSocket API3.2 DatagramPacket API3.3 InetSocketAddress API 4. UDP构建服务端客户端&#xff08;一发一收&#xff0…

osg实现鼠标框选

目录 1. 需求的提出 2. 具体实现 2.1. 禁止场景跟随鼠标转动 2.2. 矩形框前置绘制 3. 附加说明 3.1. 颜色设置说明 3.2.矩形框显示和隐藏的另一种实现 1. 需求的提出 有时需要在屏幕通过按住键盘上的某个键如Ctrl键且按住鼠标左键&#xff0c;拖出一个矩形&#xff0c;实现框…

ValueError: check_hostname requires server_hostname

使用jupyter 下载js2py 异常 !pip install js2py ValueError: check_hostname requires server_hostname 一开始以为是数据源问题&#xff0c;切换阿里云 还是这个异常 结果发现是开魔法导致的&#xff0c;关闭魔法即可

怒刷LeetCode的第23天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;贪心算法 方法二&#xff1a;动态规划 方法三&#xff1a;回溯算法 方法四&#xff1a;并查集 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;排序和遍历 方法二&#xff1a;扫描线算法 方法…

英伟达NVIDIA驱动安装

一般&#xff0c;我们新的显卡上机或者新系统可能就需要重新安装显卡驱动。或者是我们在配置深度学习环境时候&#xff0c;需要手动安装驱动。 官网地址&#xff1a;官方高级驱动搜索 | NVIDIA 我们选择好自己需要的驱动后直接安装即可 下载的时候&#xff0c;选择自己需要的驱…

计算机竞赛 深度学习卷积神经网络垃圾分类系统 - 深度学习 神经网络 图像识别 垃圾分类 算法 小程序

文章目录 0 简介1 背景意义2 数据集3 数据探索4 数据增广(数据集补充)5 垃圾图像分类5.1 迁移学习5.1.1 什么是迁移学习&#xff1f;5.1.2 为什么要迁移学习&#xff1f; 5.2 模型选择5.3 训练环境5.3.1 硬件配置5.3.2 软件配置 5.4 训练过程5.5 模型分类效果(PC端) 6 构建垃圾…

JavaSE | 初识Java(一) | JDK \ JRE \ JVM

Java初识 Java 是一门半编译型、半解释型语言。先通过 javac 编译程序把源文件进行编译&#xff0c;编译后生成的 .class 文件是由字节 码组成的平台无关、面向 JVM 的文件。最后启动 java 虚拟机 来运行 .class 文件&#xff0c;此时 JVM 会将字节码转换成平台能够理…

线程的概述

#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 功能&#xff1a;创建一个子线程 参数&#xff1a; -thread:传出参数&#xff0c;线程创建成功后&#xff0c;子线程的ID被写到…

日常工作报告生成器微信小程序源码 支持日报,周报,月报,年终终结

相信大家上班都会有做工作报告的情况吧 那么这款小程序就是大家的福音了 只要输入你的工作内容或者岗位自动生成你的工作报告 支持报,周报,月报,年终终结 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88391810 源码下载2&#xff1a;评论留言或私信…