伪文件的定义

伪文件 不用来存储数据,本身不占用任何空间。是文件系统的一部分,并按目录进行组织

目的:提供一种服务,采取和常规文件相同的访问方式进行访问。

多数情况下,伪文件用来访问内核(操作系统的核心部分)提供的服务。

类型:设备文件,命名管道,proc文件

设备文件:也称特殊文件,是物理设备的内部表示,包括计算机和网络中的每个设备都可以当作特殊文件来访问。如键盘,显示器,打印机,磁盘驱动器。

命名管道:管道功能的一个扩展,经一个程序的输出连接到另一个程序的输入上。

proc文件:运行访问内核中的信息。

Unix、Linux系统里面有文件描述符这个概念(万物皆文件),比如常规的文件,标准输入输出错误(0,1,2描述符),还有套接字,消息队列等等。 它们虽然存在文件系统中某个目录,但是不属于任何的文件系统,不占用硬盘的空间,只是在内存中作用。通过内核去管理调用,比如fifo有名管道,实际是内存缓冲区中用于进程通信的。这些文件通常被内核调用为系统提供某些功能。

参考博客

学习视频

管道的概念

  1. 管道是一种最基本的 IPC 机制, 作用于有血缘关系的进程之间

pipe函数: 创建,并打开管道。

int pipe(int fd[2]);
参数:	fd[0]: 读端。

	  fd[1]: 写端。

返回值: 成功: 0

	 失败: -1 errno

image-20210925235307404

练习:使用管道实现父子进程间通信,完成:ls | wc -l 假定父进程实现ls,子进程实现wc

ls命令正常会将结果集写到stdout,但现在会写入管道写端

wc -l命令正常应该从stdin读取数据,但此时会从管道的读端读。

要用到 pipe dup2 exec

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <cstring>


using namespace std;
    
int main(void) {
    // printf("fork 子进程 %d\n", pid);
    int fd[2];
    int ret = pipe(fd);
    pid_t pid;
    pid = fork();
    if (pid == -1) {
        perror("error pipe: ");
        exit(1);
    }else if(pid == 0) {
        close(fd[1]);
        //子进程处理
        char buf[6];
        int len = read(fd[0], buf ,sizeof buf);
        if (len == 0) {
            printf("----\n");
        }
        write(STDOUT_FILENO,buf,len);
        printf("写入完毕\n");

    }else {
        //这个是父进程
        close(fd[0]);
        char s[] = "hello world\n";
        //这个向子进程写入数据
        write(fd[1],s,strlen(s));

    }


     
    return 0;
}

进程通信的概念

  1. 进程通信的几种方式:
    1. 用 管道【父子进程 fork 之后通过 管道可以进行通信】
    2. 内存映射 【修改内存 直接改变磁盘文件】

https://pic4.zhimg.com/80/v2-a1c7303b982b50cd195b3b3d359fd57f_720w.jpg

https://pic4.zhimg.com/v2-9aba20b7e08d93a5c3044b40b830e5eb_b.jpg

进程间通信的常用方式,特征:

管道:简单

信号:开销小

mmap映射:非血缘关系进程间

socket(本地套接字):稳定

管道

实现原理: 内核借助环形队列机制,使用内核缓冲区实现。

特质;

  1. 伪文件

  2. 管道中的数据只能一次读取。

  3. 数据在管道中,只能单向流动。

局限性:

  1. 自己写,不能自己读。

  2. 数据不可以反复读。

  3. 半双工通信。

  4. 血缘关系进程间可用。

这里写图片描述

pipe函数: 创建,并打开管道。

int pipe(int fd[2]);

参数:	fd[0]: 读端。

	fd[1]: 写端。

返回值: 成功: 0

	 失败: -1 errno

管道的读写行为:

读管道:

  1. 管道有数据,read返回实际读到的字节数。

  2. 管道无数据:

    1.  无写端,read返回0 (类似读到文件尾)
      	2.  有写端,read阻塞等待。
    

写管道: 1. 无读端, 异常终止。 (SIGPIPE导致的) 2. 有读端: 1. 管道已满, 阻塞等待 2. 管道未满, 返回写出的字节个数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
        int fds[2];
        if(pipe(fds) < 0){//创建一个管道,用于父子间进行通信
                 perror("pipe");
                 return 1;
        }
        char buf[1024];//临时数组,用于存放通信的消息

        printf("Please enter:");
        fflush(stdout);
        ssize_t s =  read(0,buf,sizeof(buf)-1);
        if(s > 0){
            buf[s] = 0;
        }

        pid_t pid = fork();
        if(pid == 0){//子进程只写,关闭读端
                close(fds[0]);
                while(1){
                        sleep(1);
                        write(fds[1],buf,strlen(buf));//将buf的内容写入管道
                }
        }
        else{//父进程只读,关闭写端
              close(fds[1]);
              char buf1[1024];
              while(1){
                      ssize_t s = read(fds[0],buf1,sizeof(buf1)-1);//从管道里读数据,放入buf
                       if(s > 0){
                                buf1[s-1] = 0;
                                printf("client->farther:%s\n",buf1);
                       }
               }
      }
}

linux 信号机制

A 给 B 发送信号, B收到信号之前执行自己的代码, 收到信号,不管执行到程序的什么位置 ,都要暂停运行 ,去处理信号, 处理完毕再继续执行。 与硬件中断类似 – 异步模式。 但是 信号是软件层面上实现的中断,早期被称为 软中断

  • 信号的特质: 由于信号是通过软件方法实现, 其实现手段导致信号有很强的延时性。 但对于用户来说, 这个延迟时间非常短,不容易察觉
  • 每个进程收到的所有信号,都是由内核负责发送的,内核处理。
  • 目前 信号依然是进程间通信的主要手段之一

学习教程

我们操作系统说的中断,其实就是信号

Linux信号(signal) 机制和Linux信号量(semaphore)机制的区别

Linux信号(signal) 机制 signal,又简称为信号(软中断信号 )用来通知进程发生了异步事件。 原理: 一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。信号机制除了基本通知功能外,还可以传递附加信息。 分类:

从两个不同的分类角度对信号进行:

可靠性方面:可靠信号与不可靠信号;

与时间的关系上:实时信号与非实时信号

Linux信号量(semaphore)机制  Linux内核的信号量用来操作系统进程间同步访问共享资源。

原理:信号量在创建时需要设置一个初始值,表示同时可以有几个任务可以访问该信号量保护的共享资源,初始值为1就变成互斥锁(Mutex),即同时只能有一个任务可以访问信号量保护的共享资源。   一个任务要想访问共享资源,首先必须得到信号量,获取信号量的操作将把信号量的值减1,若当前信号量的值为负数,表明无法获得信号量,该任务必须挂起在该信号量的等待队列等待该信号量可用;若当前信号量的值为非负数,表示可以获得信号量,因而可以立刻访问被该信号量保护的共享资源。 当任务访问完被信号量保护的共享资源后,必须释放信号量,释放信号量通过把信号量的值加1实现,如果信号量的值为非正数,表明有任务等待当前信号量,因此它也唤醒所有等待该信号量的任务。

[[post/14.新语言学习记录/linux/linux基础原理杂记/linux内核理解/中断机制 | 中断机制]]