Linux高级编程:进程间的通信(二)、IPC

news2024/11/17 23:55:07

回顾

共7种方式:

古老的进程间通信方式:

        管道:

                无名管道

                有名管道

        信号

系统V IPC进程对象

        共享内存

        消息队列

        信号量集

socket通信  //网络

-------------------------

无名管道

        pipe()

特点:

        用于亲缘关系进程间

     (继承相关的文件描述符 -- 对应实际同一个管道)

管道的特点:

        1.形成的数据流

        2.FIFO(first in first out ) // -- 数据结构的特点 -- 队列(排队)

           FIFO (first in last out)//  栈的特点

        3.管道中的的数据,读取之后,就没有了

管道读写规则:

        a.读端存在,写管道

        b.独断不存在,写管道 --- 股电脑破裂  SIGPIPE 信号 --- 进程收到这信号后会被结束掉

        c.写段存在,读管道 --- 没数据,读操作阻塞

        d.写端变速存在,读管道 -- 没数据,读操作不阻塞, 立即返回  返回0 表示没数据

有名管道:

创建

        mkfifo // 在系统中创建了一个 管道文件的名字

                   // 不同的进程(毫无亲缘关系的进程)可以通过该名字  最终操作到同一个管道进而实现通信

------------------------------------------

信号通信:

 

异步、同步:

用户自定义操作:

signal   

       #include <signal.h>

       typedef void (*sighandler_t)(int);

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

       sighandler_t signal(int signum, sighandler_t handler);

        功能:

                用于向操作系统注册信号处理函数,以便在特定信号发生时执行相应的操作。

        参数:

                 @signum 是信号编号,它是一个整数,用于指定要处理的信号。

       @handler是一个函数指针,它指向的信号处理函数将在接收到 signum 指定的信号时被                                   调用。       

  • 当handler为SIG_IGN时,表示忽略此信号(需要注意的是,SIGKILLSIGSTOP信号不能被忽略)。
  • 当handler为SIG_DFL时,表示接到此信号后的动作是系统默认动作。
  • 当handler是一个函数地址时,表示当接收到对应编号的signo信号时,执行该函数。

        返回值:

       signal函数的返回值也是一个 sighandler_t 类型的函数指针,它指向之前注册        在 signum 上的信号处理函数。如果注册失败,signal 函数将返回 SIG_ERR

                

练习:

1、自定义处理信号10和12

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

void handler_10_12(int sno)
{
	printf("recieve %d\n",sno);
}

int main(int argc, const char *argv[])
{
	if(signal(SIGUSR1,handler_10_12) == SIG_ERR)
	{
		perror("signal fail");
		return -1;
	}
	if(signal(SIGUSR2,handler_10_12) == SIG_ERR)
	{
		perror("signal fail");
		return -1;
	}
	while(1)
	{
		printf("hello\n");
		sleep(1);
	}

	return 0;
}

2、通过信号处理的方式,回收僵尸态子进程   // 异步处理收尸,不阻碍父进程的操作

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<stdlib.h>
#include <sys/wait.h>

void do_wait(int sno)
{
	wait(0);
	printf("child wait\n");
}

int main(int argc, const char *argv[])
{
	if(signal(SIGCHLD,do_wait) == SIG_ERR)
	{
		perror("signal fail");
		return -1;
	}

	pid_t pid = fork();
	if(pid < 0)
	{
		perror("fork fail");
		return -1;
	}
	if(pid > 0)
	{
		int i = 0;
		while(1)
		{
			printf("father = %d\n",i++);
			sleep(1);
		}
	}
	if(pid == 0)
	{
		int i = 0;
		while(1)
		{
			printf("child = %d\n",i++);
			sleep(1);
		}
	}

	return 0;
}

3、

函数: alarm();  计数  括号内写秒数,到时发送SIGALRM信号  则说明超时1次。

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

int count;

void handler(int signo)
{
	printf("---signal---%d\n",++count);;
	if(count == 3)
	{
		printf("---timeout---\n");
		exit(0);
	}
	alarm(3);
}

int main(int argc, const char *argv[])
{
	alarm(3);
	char buf[1024] = {0};
	signal(SIGALRM,handler);
	while(1)
	{
		fgets(buf,sizeof(buf),stdin);
		count = 0;
		alarm(3);
	}

	return 0;
}

kill   

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

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

raise

        int raise(int sig)<==> kill(getpid(),int sig);  
            功能:给进程自己发送sig信号

pause

        int pause(void);
            功能:
                 进程暂停,不再继续执行,除非收到其他信号。

IPC对象:


(*)共享内存 //进程间效率最高的通信方式

shm,sem,msg

    system v :  共享内存  信号量集

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

    
    key值    // 
    申请  -- xxxget  //key <--> ipc对象 
    读写 
    关闭 
    卸载

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

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

2、ftok()创建临时键值。


            #include <sys/types.h>
            #include <sys/ipc.h>
            key_t ftok(const char *pathname, int proj_id);
                    功能:通过该函数可以将pathname指定的路径用来以
                               proj_id生成唯一的临时键值。
                    参数:@pathname 路径+名称===》任意文件,只要不会
                               被删除重建即可。
                               @proj_id  整形的数字,一般用ASCII码的单字符
                                表示与参数1的运算。

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

申请:

1、申请对象:shmget()
            

            #include <sys/ipc.h>
            #include <sys/shm.h>
                        ps aux|grep a.out
                        shared 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;

2、映射对象:shmat()
    

        void *shmat(int shmid, const void *shmaddr, int shmflg);
            功能:将指定shmid对应的共享内存映射到本地内存。
            参数:

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

3、删除对象:shmctl
    

        int shmctl(int shmid, int cmd, struct shmid_ds *buf);
            功能:
                       修改共享内存属性,也可以删除指定的共享内存对象。
            参数:@shmid 要删除的共享内存对象
                       @cmd 
                       @IPC_RMID 删除对象的宏
                       @buff  NULL 表示只删除对象。
            返回值:成功 0
                           失败 -1

练习:

// a
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>
#include<unistd.h>
#include <signal.h>

int main(int argc, const char *argv[])
{
	key_t key = ftok("/",'A');
	if (key < 0)
	{
		perror("ftok fail");
		return -1;
	}
	
	int shmid = shmget(key,1024,IPC_CREAT|0666);
	if(shmid < 0)
	{
		perror("shmget fail");
		return -1;
	}

	void *p = shmat(shmid,NULL,0);
	if(p == (void *)-1)
	{
		perror("shmat fail");
		return -1;
	}
	
	pid_t *pid = p;
	pid_t pid_b = *pid;
	printf("pid_b = %d\n",pid_b);
	while(1)
	{
		fgets(p,1024,stdin);
		kill(pid_b,10);
		printf("p = %s\n",(char *)p);
		if(strncmp((char *)p,"quit",4) == 0)
		{
			break;
		}
	}

	return 0;
}


//b
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>
#include<unistd.h>
#include<signal.h>

void handler(int signo)
{
	
}

int main(int argc, const char *argv[])
{
	key_t key = ftok("/",'A');
	if (key < 0)
	{
		perror("ftok fail");
		return -1;
	}
	
	int shmid = shmget(key,1024,IPC_CREAT|0666);
	if(shmid < 0)
	{
		perror("shmget fail");
		return -1;
	}

	void *p = shmat(shmid,NULL,0);
	pid_t *pid = p;
	*pid = getpid();
	printf("pid = %d\n",*pid);
	if(p == (void *)-1)
	{
		perror("shmat fail");
		return -1;
	}

	signal(SIGUSR1,handler);
	while(1)
	{	
		pause();
		printf("p = %s\n",(char *)p);
		if(strncmp((char *)p,"quit",4) == 0)
		{
			break;
		}

	}

	return 0;
}

消息队列 

信号量集

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

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

相关文章

CSS3笔记

1.相同优先级的样式以写在后面的为主。 2.交集选择器&#xff0c;并且 条件挨在一起 p.rich{...} /*p元素class有rich的元素*/ 3.并集选择器&#xff0c;或者 逗号隔开 .class1,class2{...}/*满足其中一个类名都会使用该样式*/ 4.后代选择器 空格 隔开 所有符合的包括孙子及…

揭秘App访问量背后的秘密:数据统计与分析

在移动互联网时代&#xff0c;App已成为人们日常生活的重要组成部分。对于App运营者来说&#xff0c;了解用户的访问量、行为习惯等数据至关重要。本文将深入探讨如何精准统计App访问量&#xff0c;为运营者提供有价值的数据支持。 一、App访问量统计的重要性 访问量是衡量A…

2024年【焊工(初级)】找解析及焊工(初级)考试技巧

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 焊工&#xff08;初级&#xff09;找解析是安全生产模拟考试一点通生成的&#xff0c;焊工&#xff08;初级&#xff09;证模拟考试题库是根据焊工&#xff08;初级&#xff09;最新版教材汇编出焊工&#xff08;初级…

【EAI 027】Learning Interactive Real-World Simulators

Paper Card 论文标题&#xff1a;Learning Interactive Real-World Simulators 论文作者&#xff1a;Mengjiao Yang, Yilun Du, Kamyar Ghasemipour, Jonathan Tompson, Leslie Kaelbling, Dale Schuurmans, Pieter Abbeel 作者单位&#xff1a;UC Berkeley, Google DeepMind, …

leetcode 移除链表元素

本题中&#xff0c;我们是要移除链表的某一个节点&#xff0c;为了确保统一操作&#xff0c;我们需要使用虚拟头节点&#xff0c;这样我们删除节点的时候&#xff0c;就是把这个要删除的节点&#xff08;当前节点cur&#xff09;的前一个节点pre&#xff0c;使得pre.next指向要…

jsp阿帕奇安装教程

1.将压缩包解压&#xff0c;存放在自己所知道的位置 2.将软件文件夹打开 使用winr &#xff0c;输入cmd运行打开 输入Java或者Javac&#xff0c;出现一大串之后表明成功 接着在所解压的软件中点开bin这个文件夹&#xff0c;找到startup.bat点击 点击之后会出现黑框&#xff0c…

Linux中断实验:定时器实现按键消抖处理

一. 简介 前面文章学习了Linux驱动按键中断实验,文章地址如下: Linux驱动按键中断实验:按键中断功能的实现-CSDN博客 本文在Linux驱动按键中断实现的基础上,使用定时器实现按键消抖处理。 二. Linux中断实验:定时器实现按键消抖处理 1. 定时器处理按键消抖的原理 按…

java使用poi、ftl将html导出word,设置视图为 页面视图

1、修改html标签&#xff0c; 加入如下内容 <html xmlns:v"urn:schemas-microsoft-com:vml" xmlns:o"urn:schemas-microsoft-com:office:office" xmlns:w"urn:schemas-microsoft-com:office:word" xmlns:m"http://schemas.microsoft.c…

【NCRE Python】

基本输入输出函数 input 函数 input 函数用于从标准输入&#xff08;如键盘&#xff09;接收用户输入的字符串。当 input 函数被调用时&#xff0c;程序会暂停执行&#xff0c;等待用户输入文本并按回车键。用户输入的文本会作为字符串返回给程序。input 函数还可以接收一个字…

【笔记版】docker常用指令---systemctl类、docker状态

systemctl [options] docker 启动&#xff1a;system start docker查看状态&#xff1a;systemctl status docker停止&#xff1a;systemctl stop docker有警告&#xff1a;service关闭了&#xff0c;但是docker.socket仍响应解决方法&#xff1a;systemctl stop docker.socket…

OSError: [WinError 1455] 页面文件太小,无法完成操作。

[问题描述]&#xff1a;OSError: [WinError 1455] 页面文件太小&#xff0c;无法完成操作。 原因1&#xff1a;线程数太大 方法&#xff1a;改小线程&#xff08;workers&#xff09;数。 原因2&#xff1a;虚拟内存太小或为0&#xff0c;调大虚拟内存。 方法&#xff1a;右键…

SL3036 DC100V降压5V 2A 低功耗 性价比低 替代MP9486A

SL3036 DC100V降压5V 2A是一款常用的电源管理芯片&#xff0c;它能够将较高的输入电压降至较低的输出电压&#xff0c;为电子设备提供稳定可靠的电源供应。其低功耗、高性价比的特点使得它在许多领域得到了广泛的应用。然而&#xff0c;对于一些对成本敏感的应用来说&#xff0…

Linux——MySQL主从复制与读写分离

实验环境 虚拟机 3台 centos7.9 网卡NAT模式 数量 1 组件包mysql-5.6.36.tar.gz cmake-2.8.6.tar.gz 设备 IP 备注 Centos01 192.168.223.123 Amoeba Centos02 192.168.223.124 Master Centos03 192.168.223.125 Slave MySQL安装 主从同时操作 安装所需要的…

SG11加密,屠龙少年最终变成了恶龙

加密只是一种手段&#xff0c;不应该成为收割工具&#xff0c;最近收到2个客户询盘&#xff0c;结果都是因为代码被加密无法提供服务&#xff0c;无奈放弃。 sg11加密的初衷是为了防止客户不遵守契约衍生出来的方案&#xff0c;没想到屠龙少年最终变成了恶龙。第一个客户因为服…

【知识整理】Git 使用实践问题整理

问题1、fatal: refusing to merge unrelated histories 一、Git 的报错 fatal: refusing to merge unrelated histories 新建了一个仓库之后&#xff0c;把本地仓库进行关联提交、拉取的时候&#xff0c;出现了如下错误&#xff1a; fatal: master does not appear to be a g…

MYSQL---日志

1.日志的概述 日志是MySQL数据库的重要组成部分。日志文件中记录着MySQL数据库运行期间发生的变化&#xff1b;也就是说用来记录MySQL数据库的客户端连接状况、SQL语句的执行情况和错误信息等。当数据库遭到意外的损坏时&#xff0c;可以通过日志查看文件出错的原因&#xff0…

QUIC来了!

什么是QUIC QUIC&#xff0c;快速UDP网络连接(Quick UDP Internet Connection)的简称&#xff0c;即RFC文档描述它为一个面向连接的安全通用传输协议。其基于UDP协议实现了可靠传输及拥塞控制&#xff0c;简单来说&#xff0c;QUIC TCP TLS。 为什么有了QUIC HTTP2.0为了为了…

京津冀国际光伏展

京津冀国际光伏展是一个国际性的光伏展览会&#xff0c;旨在推动京津冀地区光伏产业的发展&#xff0c;促进国内外光伏技术的交流与合作。展览会通常包括展览展示、技术交流、高层论坛等环节&#xff0c;吸引了来自全球各地的光伏企业、科研机构、行业专业人士等参观和参与。 京…

抖店入驻费用是多少?新手入驻都有哪些要求?2024费用明细!

我是电商珠珠 我做电商做了将近五年&#xff0c;做抖店做了三年多&#xff0c;期间还带着学员一起做店。 今天&#xff0c;就来给大家详细的讲一下在抖音开店&#xff0c;需要多少费用&#xff0c;最低需要投入多少。 1、营业执照200元左右 就拿个体店举例&#xff0c;在入…