Linux相关概念和易错知识点(23)(进程间通信、匿名管道、进程池)

PIPE4: PHY inteface for Pcie Intel PHY Inteface spec 4.4, 适用于与PCIe,SATA,USB芯片开发 立即下载

目录

1.进程间通信(IPC)

(1)为什么要有进程间通信?

(2)通信的前提

(3)通信分类

2.匿名管道

(1)管道使用及现象

(2)匿名管道原理

①struct file和inode的权限区别

②pipe的创建

③引用计数在pipe上的应用

④数据通信

a.数据不一致

b.同步互斥保护机制

c.临界资源

(3)管道的特性

(4)原子性

(5)数据不一致、匿名管道缺陷

3.进程池

(1)进程池原理

(2)不必要写端继承问题

(3)过程实现

①主程序逻辑

②进程池成员变量

③初始化进程池

④子进程处理任务

⑤分发任务

⑥销毁进程池

(4)总结


1.进程间通信(IPC)

(1)为什么要有进程间通信?

我们都知道进程具有独立性,但我们在很多时候都面临数据传输、资源共享、通知事件、进程控制等需要多个进程协同工作的场景。

(2)通信的前提

要实现通信的前提,我们先得让不同的进程看到同一份资源。同一份资源指的是某种形式的内存空间;提供资源的只能是操作系统!也就是说我们需要让操作系统提供一份公共的内存空间,这份空间就是文件内核缓冲区。还记得struct file吗?我们在这里需要复习并补充一点关于struct file的知识:

①从磁盘读取的文件会以struct file的形式展示给OS,OS的所有对文件的操作都是对file进行操作,file中有两个很重要的成员:inode和文件内核缓冲区,每个被打开的文件都只有唯一一份inode和文件内核缓冲区。也就是说,如果父子打开同一个文件,父子进程的内核缓冲区和inode都指向同一个,这就是通信的核心——让两个进程看到同一块内存空间。

②父子进程的struct file都是独立的!为什么?当不同进程访问文件内核缓冲区,它们访问缓冲区的位置是独立的,比如A进程访问缓冲区第一个字节,B进程访问缓冲区最后一个字节,A进程和B进程都需要保存当前“指针”的位置,这个位置就是保存在struct file中的。所以不同进程之间要保证部分属性的独立,这也是为了保证①不会发生读写冲突,使其逻辑严密。只是在很多情况下,我们可以简单地说一个文件对应一个struct file,但一旦涉及读写位置独立,struct file的独立性就不得不考虑了。

③文件内核缓冲区是操作系统提供的,这就是说这个缓冲区不属于某个具体的进程。在这里我们需要先接收一个观点,即OS是所有进程共享的,所有进程都会看到同一个OS。这其实也是两个进程能看到同一块空间的另一层原因。如果是属于某个进程的空间,如父子进程自己new的空间、用户空间,其它进程自然无法看到,也就无法用作公共内存空间。在这里我们可以下一个结论:凡是用作IPC的公共空间,它一定属于OS而不是某个进程,凡是属于某一个具体进程的空间一定不能用作不同进程的公共空间,在摸棱两可的情况下,这是个很好的判断方法。

④OS中几乎所有数据结构都存在引用计数,所以我们无需担心内存泄漏的情况。

(3)通信分类

通信分为本地通信和网络通信。我们当前主要介绍本地通信。

本地通信:同一台主机,同一个OS下,在不同进程之间通信。主流的有三种通信标准:system V、管道、posix。标准是指一种规范、解决方案,标准一般都是由大厂带领建立的。

2.匿名管道

(1)管道使用及现象

管道是Unix(Linux是从Unix模仿的)古老的通信方式。我们已经会使用管道了,大致上可以认为是前者的执行结果能够作为后者的已知信息。

如who | wc -l,who查看登陆当前系统有几个人登录,wc -l计算行数

在后端执行sleep 20000 | sleep 20000 &,我们可以发现管道前后的文件PPID都是一致的,这说明它们有着共同的父进程

(2)匿名管道原理

我们利用文件内存缓冲区实现匿名管道,但这是一种纯内存的文件,不需要刷新到磁盘,我们只需要它的缓冲区,没必要和磁盘挂钩。这个纯内存文件很特殊,它需要我们在具体进程中用特殊的函数代码创建,但它并不属于某个进程,这也验证了我们前面的说法。

①struct file和inode的权限区别

struct file* fd_array是每个进程都有的,它是一个结构体指针数组,其下标就是fd,当我们打开文件时,就会创建file并修改fd_array。

注意struct file中会保存当前file的读写权限,inode里面也会保存权限,这两种权限是不一样的。file具有独立性,因此不同file指向同一文件可以只读、只写、读写(动态的权限),而inode里面保存的是拥有组、所属组和other的读写情况(静态的权限)。

②pipe的创建

我们使用int pipe(int pipefd[2])创建匿名管道。pipefd是输出型参数,接收读写端的fd。返回值表示是否创建成功,创建成功返回0,否则返回-1

注意这里4和6其实是创建了两个file,分别对应读权限和写权限(不是同时打开读写权限,而是用两个fd来打开文件,一个读一个写),但它们都指向同一块文件内核缓冲区。

当我们这个时候fork,就会将fd_array完整的交给子进程

这个时候我们就实现了父子进程看到同一块资源。之后我们需要对父子进程进行处理,让它们close不必要的读端和写端(如果不关闭不必要的读写端,这会导致fd泄露,也可能会误操作,就像指针一样,这个操作不必须,但这是良好的编程习惯),这就形成了一条父子进程间的管道,子写父读或者父写子读。

管道采用创建两个file的方法来实现读写的区分,这样保证每个fd对应的是纯粹的读或者写,close不必要fd后传输数据更加安全。同时我们也发现通信是单向的,这是因为管道就是为解决单向通信诞生的,这种性质也导致它叫管道。同时这个管道没有磁盘路径,没文件名,就是个特殊的内存文件,所以叫匿名管道。

易错点:不能先创建子进程再打开pipe文件,因为要利用的进程创建的继承特性来实现拷贝文件描述符,同时打开读写权限是为了方便父子进程选择通信方式,一边读一边写。

③引用计数在pipe上的应用

当我们调用pipe函数后,父进程就有两个不同权限的file被创建,它们都指向同一块文件内核缓冲区;当fork之后就有四个file,2读2写指向该内核缓冲区。pipe采用引用计数的方法来保证不会出现内存泄露的情况,即根据指向文件内核缓冲区的指针数量来判断是否释放文件。

对于所有文件而言,当指向文件内核缓冲区的指针数量为0之后,就会主动释放该文件唯一的一份inode、文件内核缓冲区。也就是说,当我们杀掉父子进程之后,文件会自动关闭,这体现出文件的生命周期随进程这一特点,管道文件也是如此,只要指向它的父子进程关闭,文件自动释放!也就是说,就算我们的进程因为意外闪退或是我们主动exit,只要保证进程被完全杀掉,文件就不会泄露。

除了以上特点,管道文件还会检测file的权限类型,默认情况下一个正常的匿名管道是1个读端配上1个写端,当写段正常 && 读端关闭时,OS会直接用信号13(SIGPIPE)杀掉写入的进程。

对于管道来说,没有读端的一瞬间就会触发OS的13信号的发送,因为当最后一个读端被关闭时,在OS看来无论写端怎么写,这都是没有意义的,写给谁呢?可能有的人会说可以先写,再打开pipe读,但这并不符合规定,我们要避免出现这种情况,如果要实现上面的功能,请至少保持一个读端的打开。

反之,如果写端关闭,只剩下读端,OS并不会发送信号,因为此时缓冲区还有数据。至于如何判断缓冲区有没有数据,我后面会介绍的。

④数据通信

接下来我们需要具体聊聊通信的细节。两个进程的读写都使用read、write系统调用 + fd进行访问。假设子写父读,子进程write了100B的数据,若父进程一次性read 1KB数据,将子进程写的数据全部读过去,对于pipe而言,只要父进程读了的数据都会被缓冲区清理,缓冲区里只会存储没有被父进程读的数据,也就是说缓冲区的数据是一次性的。

a.数据不一致

子进程写100B父进程读1KB,这是为了父进程能够一次性读完子进程的数据。并且子进程写完100B后需要sleep一段时间,因为父子进程的数据读写竞争,子进程虽然每次写100B,但有可能在某一时间子进程写了3次而父进程就读了1次,这就会导致本来3份数据,在父进程看来只是1份更大的数据,数据内容虽不会丢失,但它的份数由3 -> 1,也就是说父进程收到的数据和子进程原本想表达的数据发生了数据不一致问题。

这个问题需要重视,最好的解决办法是子进程每次写数据要间隔一段时间,给父进程留足时间读数据,并且保证父进程每次读数据的量足够大,一次能读完子进程发送的一份数据。

b.同步互斥保护机制

子进程每次写完要sleep一段时间,给父进程留足时间读数据。那么问题来了,父进程要sleep吗?不需要,当父进程在执行read函数时,如果子进程还没有发送数据(pipe文件缓冲区为空),父进程会被阻塞在这个函数里(类似wait),读到数据后就会跳出阻塞。这是pipe管道的特殊处理(管道的同步互斥保护机制),正常文件缓冲区为空会直接返回0!

当写端关闭只剩读端时,父进程依然可以读取数据,当数据读完后,再read就不会被阻塞,这个时候就会和普通文件一样返回0,这也是判断写端有没有关闭的好办法。

总结:处于正常通信时如果文件缓冲区为空,read会一直阻塞;如果写端都被关闭,此时如果文件缓冲区为空,read就会返回0。

c.临界资源

IPC是让不同的进程看到同一块资源(共享资源),但这会面临数据不一致问题,即一个还没写完另一个就来读了,还会出现read到空的缓冲区的问题,因此我们要保护共享资源,这部分资源就叫临界资源。

(3)管道的特性

①面向字节流。父子进程可以直接读写,不管对方进程读或者写了多少次,当然这会导致数据不一致问题

②匿名管道可以用于有血缘关系的进程,一般是父子进程

③管道自带同步互斥等保护机制,管道文件同样有大小,其内核缓冲区满了就不能写了,空了就不能读。

④单次写入数据小于PIPE_BUF(如4096字节)大小就叫做单次写入具有原子性。

(4)原子性

当我们第一次写数据时,缓冲区为空。那么这里就会面临一个问题,这个时候read正在阻塞,会不会出现write写着写着就被read读走造成数据不一致问题呢?

当单次写入大小 <= 一个原子的大小的话,此次写入具有原子性,即无法被打断,只有完全写入和完全不写入两种状态,在进行原子化写入时,OS的read会被阻塞,不会出现进行原子化写入时被打断的情况。比如当写入4095个字节时,就会写入一个原子,当这个原子写入后,read才会解除阻塞;当写入4097个字节时,就会写入两个原子,这个时候注意了,当写完一个原子后,第二个原子开始写之前第一个原子就会被读走,造成数据不一致问题。所以说我们单次write大小尽量不超过一个原子的大小。

这里强调一下,原子性写入贯穿OS所有的IO流程。OS读写数据看似最小单位是1B,实际上是以一个原子的大小为单位进行的,只不过它不会让我们看到多余IO的空间。它显示只拷贝了10B,实际上硬件侧拷贝的是4096B。就好比我需要给一个人1块钱,我从银行取一百,会往自己兜里放回99,那99是不会让别人知道的,我只会告诉别人我这里有1块。

(5)数据不一致、匿名管道缺陷

上面讲述了数据不一致的两种场景,这里需要总结一下。当进行写入时,应保证单次写入不超过一个原子,这样会使得在连续写多个原子期间前面的数据被read读走,我们尽量保证缓冲区的数据在一个原子以内。但是,如果子进程连续写了两次,而父进程一次性把两个原子都读走了,也会造成数据不一致问题,所以如果要严格保证数据一致,写端写完一次要sleep,给父进程时间读走数据,父进程读数据的时候子进程可以继续向缓冲区写,两者不冲突,子进程正在写的原子父进程读不走;如果要一次写入多个原子,就要保证每次写的时候父进程不会进来读,也就是说每次读完之后读端要sleep,给子进程一点时间去写数据。

总结:由于面向字节流的特性,管道文件缓冲区没有消息边界,有可能写两次读一次,因此写后要sleep;管道文件也可能一次写两个原子,结果写一个就被读走了,所以需要读完后sleep。管道很难控制绝对的数据一致,一是父子进程至少其一要sleep,但调用没办法很好契合;二是sleep效率折损太大。所以对于这种需要多次通信的情况需要选择有消息边界的通信方案,匿名管道适合单次通信。

3.进程池

(1)进程池原理

创建进程池本质上是一种任务派发。我们预先创建进程,每个进程在需要时各自执行任务。以匿名管道为例,父进程先创建pipe,再创建子进程,父进程保存pipe和子进程一一对应的关系,循环往复创建多组pipe和子进程。父进程写,子进程读,以此实现父进程给子进程派发任务的功能,进而实现多个子进程协同操作,加快任务处理。

只要掌握了匿名管道,将读写细节搞清楚的话,进程池的实现就会轻松许多。

(2)不必要写端继承问题

对于子进程来说,它们的读端都是固定的,因为fd的占用是从前到后,先从没有使用的下标开始,且pipe占用fd都是先读后写的顺序。例如,父进程创建pipe1时占用3为读端,4为写端,其子进程的3为读端,父进程关闭3;当创建pipe2时,父进程使用3为读端,5为写端,其子进程的3为读端,以此类推。

在创建匿名管道时我们忽略了一个细节,那就是父子进程的fd数组在关闭不必要接口后出现了不必要写端继承的问题。

下面是pipe1 -> pipe2父子进程读写端的情况。 

简单来说就是每一次创建pipe,对于子进程来说都默认只会处理当前pipe的写端,但对于第二个pipe来说,它还会继承父进程第一个pipe的写端,也就是说pipe2、pipe3...都会含有pipe1的写端,pipe1写端引用计数为n,pipe3、pipe4...含有pipe2的写端(引用计数为n - 1),以此类推,仅有最后一个pipe n只有1个写端。这增加了不安全性,pipe1的读写端本就应该只由父子进程决定,却现在让pipe2、pipe3...的子进程看到了。因此,每一次创建pipe,应该让子进程先把父进程存下来的写端全部关一遍,这样每个子进程才不会得到前面pipe遗留的写端。

如果不这样做,让我们清理进程池时,使用关闭写端,让子进程read得到0进而退出进程的方法就失效了,因为对于pipe1而言,其写端有n个,关一个依然会触发同步互斥保护机制(写端引用计数不为0),让子进程read阻塞。面对这种问题,我们的解决方法最好是向上面说的那样每次清理子进程继承的多余的写端。除此之外,还有一种思路,即从pipe n对应的进程开始逆序关闭,pipe n对应子进程关闭了,其上所有pipe的写端引用计数都会 - 1,以此类推。

(3)过程实现

下面按照代码逻辑大致梳理一遍匿名管道实现进程池的过程,以加深印象

①主程序逻辑

抓住主要任务:创建进程池、处理任务、销毁进程池

②进程池成员变量

一个进程池要保存的是任务数量和子进程与其对应的pipe写端的信息,后者采用Channel类进行封装。

Channel类,就是子进程pid和父进程写端对应fd的值

③初始化进程池

父进程采用循环方式,在每一次循环中创建pipe及其子进程,当子进程得到pipe之后关闭父子进程不必要的读写端,父进程用Channel对象记录子进程的pid及其写端。

对于子进程而言,当它的准备工作做好之后就应该进入read函数,阻塞着等待父进程发放命令。

下面是初始化代码,先大致看一下,验证上面的流程,后面会详细讲解。

enum ProcessPool_state
{
    ExecuteComplete,
    ExecuteError,
    PipeError,
    NumError,
};

class ProcessPool
{
public:
    ProcessPool(int count, int num_of_tasks)
        : _num_of_tasks(num_of_tasks)
    {
        if (count <= 0)
        {
            cout << "创建的子进程数量必须 >= 1" << endl;
            exit(NumError); // 直接退出,exit不会调用析构函数
        }

        for (int i = 0; i < count; i++) // 创建count个子进程
        {
            int pipefd[2] = {0, 0};

            // 创建匿名管道
            int ret_creat_pipe = pipe(pipefd);
            if (ret_creat_pipe == 0)
                printf("第%d个匿名管道创建成功,读端fd为%d,写端fd为%d\n", i + 1, pipefd[0], pipefd[1]);
            else
            {
                printf("第%d匿名管道创建失败\n", i + 1);
                exit(PipeError); // 直接退出程序,先前创建的匿名管道会因为引用计数为0自动销毁
            }

            // 创建进程使用匿名管道
            pid_t ret_fork = fork();
            if (ret_fork == 0) // 子进程
            {
                // 父进程写,子进程读,父进程给子进程派发任务
                ::close(pipefd[1]); // 子进程关闭写端


                dup2(pipefd[0], 0); // 将读端覆盖标准输入流,后续只需要从0读数据就能知道父进程的安排
                ::close(pipefd[0]); // 相当于将fd移位到0
                     

                for (auto &e : _pipe_array)
                {
                    ::close(e.Getwritefd()); // 将父进程遗留下来的写端都关闭,子进程只会调用读端
                }
         
                printf("第%d个子进程准备就绪,开始等待处理任务\n", i + 1);
                ProcessTask();
            }

            // 只有父进程能走到这里
            ::close(pipefd[0]); // 父进程关闭读端
            // 父进程要向多个pipe写文件,而子进程只从一个pipe读文件,所以父进程不能直接dup2

            // 将子进程的pid和父进程写端的fd记录下来,方便后续管理子进程以及分配任务
            _pipe_array.emplace_back(ret_fork, pipefd[1]);
            printf("第%d个子进程和及其匿名管道数据已被父进程记录\n", i + 1);
        }
    }

④子进程处理任务

其中ProcessTask()函数就是让子进程进入处理任务的状态,时刻read等待父进程下达命令。

这里使用了死循环使得一个子进程时刻接收任务、处理任务。如果写端关闭,子进程读完数据后就不再触发同步互斥保护机制,返回0,我们利用这种特性来关闭读端,进而退出进程。

⑤分发任务

初始化完成后就是要分发任务了,我们采用轮询的方式让每个进程都公平的得到任务,获取任务编号写到对应的管道里,子进程的read就会读到数据并开始处理,当处理完之后又能得到新的任务并继续处理。注意这里我没有使用sleep来强制保证数据一致,这也是我们代码的弱点之一。

其中我们将任务类单独封装了,用于任务的获取和调用。

using task_t = function<void()>;


void taskA()
{
    cout << "正在执行任务A" << endl;
}
void taskB()
{
    cout << "正在执行任务B" << endl;
}
void taskC()
{
    cout << "正在执行任务C" << endl;
}
void taskD()
{
    cout << "正在执行任务D" << endl;
}



class Task
{
public:

    int size()
    {
        return (int)_task_array.size();
    }
    Task()//加入四个任务
    {

        _task_array.reserve(sizeof(task_t) * 4);

        srand((unsigned int)time(nullptr));
        _task_array.push_back(taskA);
        _task_array.push_back(taskB);
        _task_array.push_back(taskC);
        _task_array.push_back(taskD);
    }

    int SelectTask()
    {
        return rand() % _task_array.size();
    }

    void ExecuteTask(int num)
    {
        if(num < 0 || num >= 4)
        {
            printf("当前任务码为%d,异常!\n", num);
            exit(1);
        }

        printf("开始处理任务,任务码为%d\n", num);

        fflush(stdout);

        _task_array[num]();//执行对应任务
    }

private:
    vector<task_t> _task_array;

}task;

⑥销毁进程池

分完任务并处理完之后就需要销毁进程池了。由于在初始化进程池时我们就解决了不必要写端继承的问题,关闭写端后,子进程就会依序退出,我们的父进程阻塞式等待子进程即可。

(4)总结

通过进程池的代码,我们能够进一步深入了解进程间通信的原理,其中最难理解的就是数据不一致问题,匿名管道的面向字节流就决定了它不适合多次数据传输,不过我们依然使用它走完了进程池的流程,了解即可。在整个过程中,读写端都将对方当作了文件,都是对pipe文件进行IO,这再次体现出Linux一切皆文件的思想,值得我们体会。

pipe4 立即下载

相关推荐

pipe接口协议

该文档为最新5.1的PIPE接口协议,讲述PCS与MAC层之间的数据通信 。

linux管道pipe详解

管道 管道的概念: 管道是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。调用pipe系统函数即可创建一个管道。有如下特质: 1. 其本质是一个伪文件(实为内核缓冲区) 2. 由两个文件描述符引用,一个表示读端,一个表示写端。 3. 规定数据从管道的写端流入管道,从读端流出。 管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。 管道的局限性: ① 数据自己读不能自己写。 ② 数据一旦被读走,便不在管道中存在,不可反复读取。 ③ 由于管道采用半双工通

木牛的博客 7372

ESP32—C3实现网页跳转

用户点击HTML页面中的按钮。浏览器根据按钮的href属性向服务器发送HTTP GET请求。服务器根据请求的URL调用相应的回调函数。服务器发送包含新页面HTML内容的HTTP响应。浏览器解析并显示新的HTML页面。这个过程对于用户来说是无缝的,看起来就像是直接从一个页面跳转到另一个页面。实际上,背后发生了HTTP请求和响应的过程。

qq_59527512的博客 1022

【亲测免费】 PIPE4: PHY接口规范下载 - 助力高效芯片开发

PIPE4: PHY接口规范下载 - 助力高效芯片开发 【下载地址】PIPE4PHY接口规范下载分享 PIPE4: PHY接口规范下载 项目地址: https://gitcode.com/Open-source-documenta...

gitblog_06607的博客 922

AI视频生成提示词工程:结构化公式与实战案例详解

在实际使用 AI 生成视频或图像时,最常遇到的困惑是:为什么我的提示词(Prompt)生成的画面总是不理想?是模型能力不足,还是我的描述有问题?答案往往是后者。提示词工程(Prompt Engineering)并非简单的“翻译”需求,而是一门需要结构化思维和精准描述的技能。它决定了 AI 能否准确理解你的意图,并生成符合预期的视觉内容。 本文将通过两个核心案例,深入拆解提示词的构建逻辑。第一个案例聚焦于“文生视频”,我们将学习如何将一个简单的想法,如“小猫在雪地里玩雪球”,通过结构化公式扩展为一段富有细节和

weixin_30800987的博客 557

EtherCAT丢包问题深度解析:从原理到实战排查指南

在工业自动化与运动控制领域,实时通讯网络的稳定性是系统可靠运行的基石。EtherCAT(以太网控制自动化技术)作为一种高性能工业以太网协议,其核心在于独特的“飞读飞写”机制和纳秒级的分布时钟同步,以实现多设备间的精准协同。然而,物理链路干扰、配置不当或硬件性能瓶颈都可能导致数据帧丢失,破坏时钟同步,进而引发伺服抖动、定位精度下降乃至生产线停机。本文聚焦于EtherCAT丢包这一典型故障,结合SSC(Slave Stack Code Tool)从站协议栈开发与实时系统调优等工程实践,系统阐述其成因、影响及一套

weixin_32050773的博客 341

pipe

#include #include #include #include #include #include int main() {     int pipe_fd[2];     pid_t pid;     char r_buf[100];     char w_buf[4];     char *p_wbuf;     int r_num;     int

krysen的博客 329

2025华为OD面试手撕代码真题目录、八股文真题目录以及面试技巧

1. **华为OD面试技术面准备指南** 2. **华为OD面试技术面常见问题解答** 3. **华为OD面试技术面经验分享** 4. **华为OD面试技术面注意事项** 5. **华为OD面试技术面攻略** 6. **华为OD面试技术面模拟题目与解析** 7. **华为OD面试技术面知识点梳理** 8. **华为OD面试技术面常考**

算法大师! 3万+

PIPE4:快速PPI预测器,用于综合的跨物种和跨物种相互作用组

对更大规模且日益复杂的蛋白质-蛋白质相互作用(PPI)预测任务的需求,要求最先进的预测器高效且适应跨物种预测。此外,生成综合相互作用组的能力使得在所有预测背景下评估每个PPI成为可能,从而进一步提升了在极端类别不平衡情况下的分类性能,利用互惠视角(RP)框架实现。我们在这里描述PIPE4算法。PIPE3/MP-PIPE序列预处理步骤的适应使得速度提升了50倍以上,新的相似度加权评分在应用于任何跨物种和跨物种预测模式时,能够适当归一化窗口频率。

nap-joker的博客 470

vue2 - 详细实现播放AMR格式音频并实现自定义播放器样式,支持amr音频文件在线地址URL播放、调用服务端API接口获取二进制文件流amr形式、用户本地上传amr文件并实现立即播放(详细代码)

vue2,amr,amr文件播放,vue播放amr音频文件以及在线url跨域问题解决,vue使用audio标签播放amr音频,amr跨域解决,amr网页解码播放,文件上传后怎么播放,vue2播放.amr语音文件,api接口形式调用获取的amr如何播放,vue中如何使用audio元素播放AMR格式的文件,进度条,vue前端如何播放AMR格式的音频文件,vue播放语音文件AMR格式,播放amr格式音频AMR录音机,h5原生audio播放amr格式的音频,VUE2使用benz-amr-recorder 实现解码、

✅ 精选推荐文章 7414

【ACP】2025-最新-疑难题解析- 练习二汇总

全球加速是优化公网访问的,负载均衡是分发流量的,公网 NAT 网关是处理公网 IP 的,高速通道是建私网连接但不直接提供固定私网地址功能。C 是客户端加密方式,D 是 ECS 云盘加密,都不属于 OSS 服务器端加密。某企业想使用云服务器 ECS + 负载均衡 SLB + 弹性伸缩 (Auto Scaling) 的架构搭建一个企业级门户网站,技术负责人对于负载均衡和弹性伸缩配合使用没有经验,于是将他理解的两种产品配合使用的一些技术细节列成了一个表单,并请作为架构师的您帮他做一下鉴别,以下哪些项是正确的?

jundao1997的专栏 293

【Linux】匿名管道通信场景——进程池

基于匿名管道通信实现的进程池,子进程会根据接受到的信息执行不同的任务,父进程可以看作Master来进行管理创建的多个进程。关键点在于对进程管理的封装以及回收子进程时会有多个进程指向匿名管道的读端,所以回收时要注意可能会出现的bug。

Renswc的博客 2906

C#工业通信完整项目实战:从协议解析到数据库存储,打造工业级全链路数据闭环(完整可复用源码)

工业自动化的核心诉求是「数据闭环」:从工业设备采集真实生产数据 → 解析校验获得有效数据 → 持久化存储到数据库形成生产台账 → 数据分析/报表展示/异常预警,形成采集→解析→处理→存储→应用的全链路数据流转,这也是工业上位机开发的终极落地形态,区别于单纯的「数据采集」demo。本次实战是一套工业级完整投产级项目,基于C# WinForm + .NET Framework 4.8(工业标配)✅双通信链路完美适配:同时封装TCP网口 + 串口(RS232/485)

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1035

【Linux笔记】进程间通信——匿名管道||进程池

简介进程间通信(IPC,Inter-Process Communication)是操作系统中不同进程之间交换数据、协调工作的核心机制。由于每个进程拥有独立的内存空间,彼此隔离,因此需要特定的技术手段实现跨进程协作。进程间通信(IPC)是指运行在同一台计算机或不同计算机上的多个进程之间进行数据交换和通信的技术。由于每个进程都有自己的地址空间,它们无法直接访问彼此的数据,因此需要通过特定的机制实现通信。IPC是操作系统和多进程编程中的一个重要概念,广泛应用于分布式系统、多任务操作系统以及各种应用程序之间。

GGDxianv的博客 1581

【知识分享】什么是同轴传输线结构?

同轴传输线的几何形状由中心导体组,嵌在介电材料(Dielectric)中,并且,被连续的外导体所包围,也被称为屏蔽(Shield)。内外导体有相同的几何中心轴,因此得名同轴(Coaxial)。

一只豌豆象的博客 2372

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【Linux篇章】进程通信黑科技:匿名管道的暗码传递与命名管道的实名使命

本文主要探讨进程间通信中的匿名管道和命名管道。将介绍匿名管道如何凭借其隐蔽性在进程间实现数据传输,以及命名管道因具备可命名的特性所带来的独特通信优势;同时会进行相关示例效果演示;代码编写;带读者一步步理解所谓的匿名管道和命名管道等。

羑悻的博客. 5304

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Linux进程间通信【匿名管道】

进程间通信简称为IPC(Interprocess communication),是两个不同进程间进行任务协同的必要基础。进行通信时,首先需要确保不同进程之间构建联系,其次再根据不同的使用场景选择不同的通信解决方案,本文主要介绍的通信解决方案为匿名管道

北 海的博客 1万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Linux进程间通信之匿名管道

进程间通信介绍 1. 进程间通信的目的 2. 进程间通信发展 什么是管道 匿名管道 1. 什么是匿名管道 2. 匿名管道样例详解 3. 原理 4. 单个父进程与多个子进程管道间通信 建立子进程任务相关的头文件 主文件的建立 执行结果 5. 管道读写规则 6. 管道特点

立志做一个高产且细节博主 2145

【Linux】————进程间通信(匿名管道)

1.一个冷知识:屏蔽力是一个人最顶级的能力,任何消耗你的人和事,多看一眼都是你的不对。2.你不用变得很外向,内向挺好的,但需要你发言的时候,一定要勇敢。正所谓:君子可内敛不可懦弱,面不公可起而论之。3.成年人的世界,只筛选,不教育。4.自律不是6点起床,7点准时学习,而是不管别人怎么说怎么看,你也会坚持去做,绝不打乱自己的节奏,是一种自我的恒心。5.你开始炫耀自己,往往都是灾难的开始,就像老子在《道德经》里写到:光而不耀,静水流深。

bhbcdxb123的博客 2248

【Linux进程间通信】匿名管道、命名管道、进程池

本文介绍了进程间通信的第一种方法:管道通信,详细讲解了其原理和实现方法,从匿名管道和命名管道两方面介绍了其特性,并给出匿名管道的应用--进程池和命名管道的应用 两个实现的完整代码,帮助深入理解和认知管道的特性和使用。

2301_80555259的博客 1707

linux进程间通信——匿名管道、简易进程池、pipe应用

linux进程间通信——管道实战——进程池实现!!!

strive_mianyang的博客 2676

进程池的制作(linux进程间通信,匿名管道... ...)

在程序使用内存的时候,比如vector扩容机制,会提前给你开辟一块空间供你使用,尽管现在用不到,相当于做一下预备。因为只是一个小测试,代码写的并不严谨(没有检查调用是否成功,没有关闭文件,没有进程等待)大家不用太在意,能说明问题就行。,但它与一般的文件还是有些区别,文件都是储存到磁盘上的,而进程之间通信用的文件并不需要把它储存到磁盘上,它只是作为一个传输介质。那么进程池也同样,给父进程提前开辟一些子进程,提供父进程使用。,顾名思义就是没有名字,也不需要名字,因为子进程能够继承下来父进程开辟的管道资源。

2302_80105876的博客 1629

Linux 进程间通信 管道系列: 匿名和命名管道,自定义shell当中命令行管道的模拟实现

Linux 进程间通信 管道系列: 匿名和命名管道,自定义shell当中命令行管道的模拟实现

Wzs040810的博客 2412

【Linux篇】探索进程间通信:如何使用匿名管道构建高效的进程池

管道(Pipe)是一种进程间通信(IPC)机制,允许一个进程将数据传输到另一个进程。管道提供了一种简单、高效的方式来在同一台机器上的进程之间传递数据,常见于父子进程或兄弟进程之间的通信。管道通过一个缓冲区传递数据,发送进程将数据写入管道,而接收进程从管道中读取数据。进程池是一种多进程并发处理模型,它通过预先创建一定数量的进程来处理任务,从而避免了在每个任务执行时频繁创建和销毁进程的开销。进程池中的进程通常在任务到达时被复用,任务完成后,进程不会被销毁,而是返回进程池等待下一个任务。

braveact的博客 1589

从零实现一个简易进程池:基于匿名管道的任务分发模型

本文深入解析了进程间通信(IPC)的概念与实现方式。文章首先指出进程独立性导致通信困难,需要通过操作系统提供的共享资源实现数据交互。重点介绍了匿名管道通信机制,其本质是让父子进程共享内存级文件资源,通过pipe()系统调用创建单向通道。文章详细分析了管道的4种工作状态、字节流特性及生命周期随进程的特点,并通过一个进程池的完整案例演示了多进程+管道通信的实际应用。案例展示了父进程分发任务、子进程执行任务的模型,特别强调了正确管理文件描述符的重要性,最后提供了完整的代码实现。

2302_77620024的博客 7766

【Linux系统】理解管道通信,匿名管道实现进程池+命名管道实现服务端客户端通信模型(附源码)

本文介绍了进程间通信(IPC)的基本概念与管道实现方式。进程间通信包括数据传输、资源共享等功能,主要通过管道、System V IPC和POSIX IPC实现。管道分为匿名管道和命名管道:匿名管道用于亲缘进程间单向通信,通过pipe系统调用创建,具有单向性、字节流传输等特点;命名管道通过mkfifo创建,允许无关进程间通信。文章还演示了匿名管道的C语言实现代码,并提供了一个进程池的C++实现示例,展示了如何利用管道进行多进程任务分配。最后强调了管道通信自带同步机制的特点,以及读写端关闭时的不同处理方式。

记录我一步步的学习历程,期待无限进步,向星举目! 1102
上一篇: Linux相关概念和易错知识点(22)(ELF格式、可执行程序的加载、共享库)
下一篇: Linux相关概念和易错知识点(24)(认识信号、信号捕捉)
-SGlow-
博客等级 码龄3年 1513粉丝 118原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值