进程间通信

2024-01-09

进程间通信

进程间通信介绍

进程间通信目的

  • 数据传输:一个进程需要将它的数据发送给另一个进程

  • 资源共享:多个进程之间共享同样的资源。

  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止

    时要通知父进程)。

  • 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另

    一个进程的所有陷入和异常,并能够及时知道它的状态改变。

进程间通信发展

  • 管道
  • System V进程间通信
  • POSIX进程间通信

进程间通信分类
管道

  • 匿名管道pipe
  • 命名管道

System V IPC

  • System V 消息队列
  • System V 共享内存
  • System V 信号量

POSIX IPC

  • 消息队列
  • 共享内存
  • 信号量
  • 互斥量
  • 条件变量
  • 读写锁

进程间通信的本质

进程间通信的本质就是让不同的进程看到同一份资源(文件等等),然后进行交流(调用系统接口)

后者我们十分的熟悉,我们之前调用了很多个系统接口(fork,reak,write等等)

所以进程间通信的本质就是让不同资源看到同一份资源

image-20231113150409545

管道

什么是管道

管道是Unix中最古老的进程间通信的形式。
我们把从一个进程连接到另一个进程的一个数据流称为一个“管道“

image-20231113145149859

我们之前说进程间通信的本质是让不同的进程看到同一份资源,管道就是其中的一种资源

  • 管道分为匿名管道和命名管道

匿名管道

进程间通信的本质就是让不同资源看到同一份资源

而匿名管道的本质就是让父子进程看到同一个文件(pipe),这样父进程进行写入或者读取,子进程负责读取或者写入,这样就可以完成进程间通信

image-20231113152316047

我们在Linux中多次强调过,Linux下一切皆文件,因此管道也是一个文件

我们父进程在创建的时候,会默认打开0,1,2这三个文件描述符,会让磁盘会将信息加载到内存中struct file这个结构体里面,这里包含了操作方法和内部缓冲区

此时,我们父进程fork子进程的时候,不会拷贝匿名管道(struct file)这个文件,因为创建进程跟文件没有关系,但是files_struct会被拷贝,因为它属于进程的一部分,并拷贝了其中的文件描述符,曾经父进程打开的内容,子进程也会被映射,此时父进程打开同一份文件,就相当于看到了同一份资源,这个时候只要父进程写入,子进程读取就相当于完成了进程间通信

pipe函数

pipe函数用于创建匿名管道

#include <unistd.h>
int pipe(int pipefd[2]);

pipefd是一个输出型参数,pipefd[0]和pipefd[1]分别代表读取段和写入端

pipe成功返回0,失败返回-1

image-20231113192208276

用fork共享匿名管道原理

父进程调用pipe系统接口

image-20231113192822197

父进程fork后,也就是pipe的读端指向父子进程,pipe的写端也指向父子进程

image-20231113193113724

父进程关闭读端,子进程关闭写端

image-20231113193240796

注意:

  • 匿名管道只能用于有亲戚关系的进程,如父子进程,爷孙进程等等
  • 管道只有单向性
  • 从管道写端写入的数据会被内核缓冲,直到从管道的读端被读取。

站在文件描述符角度-深度理解管道

父进程调用pipe系统接口

image-20231113194319529

父进程fork后,也就是pipe的读端指向父子进程,pipe的写端也指向父子进程

image-20231113195816923

父进程关闭读端,子进程关闭写端

image-20231113195854828

站在内核角度-管道本质

image-20231113200440873

所以,看待管道,就如同看待文件一样!管道的使用和文件一致,迎合了“Linux一切皆文件思想”。

当父进程关闭管道的写端,子进程是怎么知道父进程关了的?并且后面还把数据读完就关了呢?

  • 父进程创建了子进程之后,在文件对应的属性中有引用计数,表示有多少个指针指向改进程,因此如果引用计数为1,说明该进程只要一个人在用,因此只要这个人读完就代表文件结束了。

因此,父进程和子进程在读写的时候,是有一定的顺序性的。

管道内部,没有数据的时候,reader就必须阻塞等待(将当前进程的take_struct放入等待队列中),等待管道有数据;如果数据被写满,writer就必须阻塞等待,等待管道中有空间。不过呢,在父子进程各自printf的时候(向显示器写入【显示器也是文件】),并没有什么顺序,因为缺乏访问控制。而管道内部是有顺序的,因为它自带访问控制机制,同步和互斥机制。

管道读写规则

  • O_NONBLOCK设置两个新的打开文件描述的O_NONBLOCK文件状态标志。使用为达到相同的结果,该标志省去了对fcntl(2)的额外调用。

  • 在两个新的文件描述符上设置close-on-exec (FD_CLOEXEC)标志。看到open(2)中同一标志的描述,原因是这可能有用。

当管道内没有数据可读时:

  • O_NONBLOCK disable:read调用一直阻塞,一直等到有数据来到为止。
  • O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。

当管道满的时候

  • O_NONBLOCK disable: write调用阻塞,直到有进程读走数据
  • O_NONBLOCK enable:调用返回-1,errno值为EAGAIN

如果所有管道写端对应的文件描述符被关闭,则read返回0
如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程
退出
当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。

我们这里解释一下原子性这个概念

原子性你可以理解为就只有两种状态要么做完了,要么没做

匿名管道特点

  • 只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创

    建,然后该进程调用fork,此后父、子进程之间就可应用该管道。

  • 管道提供流式服务

  • 一般而言,进程退出,管道释放,所以管道的生命周期随进程

  • 一般而言,内核会对管道操作进行同步与互斥

  • 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道

在数据通信中,数据在线路上的传送方式可以分为以下三种:

  • 单工通信(Simplex Communication):单工模式的数据传输是单向的。通信双方中,一方固定为发送端,另一方固定为接收端。
  • 半双工通信(Half Duplex):半双工数据传输指数据可以在一个信号载体的两个方向上传输,但是不能同时传输。
  • 全双工通信(Full Duplex):全双工通信允许数据在两个方向上同时传输,它的能力相当于两个单工通信方式的结合。全双工可以同时(瞬时)进行信号的双向传输。

管道是半双工的,数据只能向一个方向流动,需要双方通信时,要建立起两个管道:

image-20231113202056914

命名管道

  • 匿名管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
  • 如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
  • 命名管道是一种特殊类型的文件

如何常见一个命名管道

命名管道可以从命令行上创建,命令行方法是使用下面这个命令:

$ mkfifo filename

我们发现我们的命名管道文件mypipe2是一个p类型文件

image-20231113202910116

命名管道也可以从程序里创建,相关函数有:

int mkfifo(const char *pathname, mode_t mode);

mkfifo函数

函数原型:

 #include <sys/types.h>
 #include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);

mkfifo有两个参数pathname和mode

pathname参数:表示要创建的命名管道文件

  • 如果pathname是一个路径的话,这个管道文件就创建在pathname这个路径下
  • 如果path是文件名的话,就将这个管道文件默认创建在当前这个路径下

moded是默认权限

返回值:

  • 创建成功返回0,创建失败返回-1
#include<iostream>
using namespace std;
#include<sys/types.h>
#include<sys/stat.h>
#define FILE_NAME "myfifo"
int main()
{
    if (mkfifo(FILE_NAME, 0666) < 0)
    {
        cerr << "mkfifo error" << endl;
        return 1;
    }
    //create success
    cout << "hello world" << endl;
}

实际上创建出来文件的权限值还会受到umask(文件默认掩码)的影响,实际创建出来文件的权限为:mode&(~umask)。umask的默认值一般为0002,当我们设置mode值为0666时实际创建出来文件的权限为0664。若想创建出来命名管道文件的权限值不受umask的影响,则需要在创建文件前使用umask函数将文件默认掩码设置为0。

umask(0); //将文件默认掩码设置为0

匿名管道与命名管道的区别

  • 匿名管道由pipe函数创建并打开。

  • 命名管道由mkfifo函数创建,打开用open

  • FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完

    成之后,它们具有相同的语义。

命名管道的打开规则

当前打开操作是读:

  • O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
  • O_NONBLOCK enable:立刻返回成功

当前打开操作是写:

  • O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
  • O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

system V共享内存

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到
内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据

system V共享内存原理:

共享内存的底层原理跟两种管道不太一样,共享内存是通过在物理内存中申请一块空间用来充当共享内存,在通过页表的映射关系与进程的地址空间中的共享内存构建映射关系,从而完成进程间通信

image-20231114171525929

这里所说的开辟物理空间、建立映射等操作都是调用系统接口完成的,也就是说这些动作都由操作系统来完成。所以操作系统需要提供具有如下功能的接口:

  • 创建共享内存 —— 删除共享内存(OS内部帮我们做)
  • 关联共享内存 —— 去关联共享内存(进程做,实际也是OS做)

共享内存数据结构

在系统当中可能会有大量的进程在进行通信,因此系统当中就可能存在大量的共享内存,那么操作系统必然要对其进行管理,所以共享内存除了在内存当中真正开辟空间之外,系统一定还要为共享内存维护相关的内核数据结构。共享内存的数据结构如下:

struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */
__kernel_time_t shm_dtime; /* last detach time */
__kernel_time_t shm_ctime; /* last change time */
__kernel_ipc_pid_t shm_cpid; /* pid of creator */
__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
unsigned short shm_nattch; /* no. of current attaches */
unsigned short shm_unused; /* compatibility */
void *shm_unused2; /* ditto - used by DIPC */
void *shm_unused3; /* unused */
};

共享内存函数

shmget函数创建共享内存

函数原型:

 #include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);

shmget有三个参数

  • key:表示共享内存在系统中的唯一标识
  • size:共享内存大小(建议设置为页[4KB]的整数倍)
  • shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的

返回值:

  • 成功:shmget()返回与参数值关联的System V共享内存段的标识符
  • 失败:返回-1

❓为什么要建议将size设为4KB的整数倍呢?

????一个新的共享内存段,其size等于size的值向上取整为PAGE_SIZE(4KB)的倍数,我们假设有4GB的空间,约等于2^20次方个页,对于这么多页,操作系统需要把共享内存上的这么多页管理起来,依旧是先描述,再组织,OS内部用数组的方式将页保存了起来(struct page mem[2^20])。

shmflg

shmflg常见有两个标识符: IPC_CREAT和IPC_EXCL

  • IPC_CREAT:当内存中有与key值相等的共享内存的话,就返回key值,如果没有的话就创建一个共享内存,并将其的标识符设为key值
  • IPC_CREAT:IPC_CREAT不能单独使用,必须和IPC_CREAT配合,如果存在标识符为key值的共享内存的话,就报错返回,如果没有就创建一个标识符为key值的共享内存

换句话说:

使用组合IPC_CREAT,一定会获得一个共享内存的句柄,但无法确认该共享内存是否是新建的共享内存。

使用组合IPC_CREAT | IPC_EXCL,只有shmget函数调用成功时才会获得共享内存的句柄,并且该共享内存一定是新建的共享内存。

key

共享内存是存放在内核中的,内核会为我们维护共享内存的结构,那如何管理呢?依旧是先描述再管理

我们再来看看内核中共享内存的结构体:

struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */
__kernel_time_t shm_dtime; /* last detach time */
__kernel_time_t shm_ctime; /* last change time */
__kernel_ipc_pid_t shm_cpid; /* pid of creator */
__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
unsigned short shm_nattch; /* no. of current attaches */
unsigned short shm_unused; /* compatibility */
void *shm_unused2; /* ditto - used by DIPC */
void *shm_unused3; /* unused */
};

我们发现第一个变量是一个ipc_perm结构体类型的变量,而我们的key值就存放在这个结构体中

struct ipc_perm {
	key_t          __key;    /* Key supplied to shmget(2) */
	uid_t          uid;      /* Effective UID of owner */
	gid_t          gid;      /* Effective GID of owner */
	uid_t          cuid;     /* Effective UID of creator */
	gid_t          cgid;     /* Effective GID of creator */
	unsigned short mode;     /* Permissions + SHM_DEST and SHM_LOCKED flags */
	unsigned short __seq;    /* Sequence number */
};

ipc_perm结构体的第一个变量是key,而这个key是标识共享内存的唯一标识符

一个key代表一个共享内存,因此我们如何获取跟之前不同的key值呢?

ftok函数获取key值

我们上文说到了我们需要不同的key值,因此就出现ftok函数,我们可以通过 ftok函数来获取不同的key值

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);

我先来介绍这两个参数:

  • pathname为一个已存在的路径名
  • proj_id:为一个整数标识符

ftok函数会通过pathname和proj_id的最低八位(必须非0)这两个参数生成一个key值,而这个key值被称IPC键值

如果ftok函数调用成功的话,就会返回这个key值,如果失败就会返回-1

而这个key值也是就IPC键值在shmget函数调用的时候会被填充到ipc_perm这个结构体内

如果我们想要通过共享内存进行进程间通信的话:

我们可以传入相同的pathname和proj_id的值,这样就会生成相同的key值从而看到同一块共享内存

shmctl函数释放共享内存

此时我们若是要将创建的共享内存释放,有两个方法,一就是使用命令释放共享内存,二就是在进程通信完毕后调用释放共享内存的函数进行释放。

我们可以通过ipcs命令来查看共享内存的信息:

$ ipcs

image-20231118154751717

如果我们单独用ipcs命令他会自动跳出消息队列,共享内存以及信号量的信息,ipcs命令可以带很多选项:

  • -q:列出消息队列相关信息。
  • -m:列出共享内存相关信息。
  • -s:列出信号量相关信息。

image-20231118155018511

我们看到共享内存中有很多变量,我们来了解一下他们的含义:

变量 含义
key 系统层面的标识符
shmid 用户层面的唯一标识符
owner 所有者
perms 权限
bytes 共享内存的大小
nattch 关联共享内存的进程数量
status 共享内存的状态

在共享内存列表中的perms代表的是该共享内存的权限,这个是可以修改的:

int shmid = shmget(key, MEM_SIZE, flags | 0666);

注意:

key是在内核层面上保证共享内存唯一性的方式,而shmid是在用户层面上保证共享内存的唯一性,key和shmid之间的关系类似于fd和FILE*之间的的关系。

如果我们想要显示的删除,就使用ipcrm -m shmid:

$ ipcrm -m shmid

我们可以通过系统接口去释放共享内存

#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

参数

  • shmid:由shmget返回的共享内存标识码
  • cmd:将要采取的动作(有三个可取值)
  • buf:指向一个保存着共享内存的模式状态和访问权限的数据结构

返回值:成功返回0;失败返回-1

关于cmd的三个可取值:

选项 含义
IPC_STAT 获取当前的共享内存的关联值,且buf为输出型参数
IPC_SET 在进程有足够权限的前提下,将共享内存的当前关联值设置为buf所指的数据结构中的值
IPC_RMID 删除共享内存

shmat函数关联共享内存:

 #include <sys/types.h>
 #include <sys/shm.h>
 void *shmat(int shmid, const void *shmaddr, int shmflg);

我们来认识shmat的三个参数:

  • shmid:用户层面的唯一标识符
  • shmaddr:要连接的地址,通常为NULL,OS会自动给你找一个合适的地址
  • shmflg:标识符,他有3个可能取值SHM_RND和SHM_RDONLY还有个0

返回值:成功返回一个指针,指向共享内存第一个节;失败返回-1

shmflg有三个可能取值我们来了解一下:

选项 含义
SHM_RDONLY 关联共享内存后只能进行读取操作
SHM_RND 若shmaddr不为NULL,则关联地址自动向下调整为SHMLBA的整数倍。公式:shmaddr-(shmaddr%SHMLBA)
0 读写权限

说明:

shmaddr为NULL,核心自动选择一个地址
shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr -(shmaddr % SHMLBA)
shmflg=SHM_RDONLY,表示连接操作用来只读共享内存

shmdt函数去关联共享内存

有关联共享内存的函数,肯定也有去关联的函数啊!

#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);

参数
shmaddr: 由shmat所返回的指针
返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段

共享内存与管道进行对比

从上文的描述中,我们可以清晰的得知,当共享内存建立完后,我们不需要再进行系统的调用,而管道建立后还需进行read和write等系统接口的调用,因此从访问速度上讲的话,共享内存的速度肯定是最快的

我们先来看看管道通信:

image-20231118162812191

我们观察上图的话,很明显可以发现管道通信的话我们需要进行4次拷贝

  1. 服务端将信息从输入文件拷贝到输入文件的缓冲区中
  2. 将服务端的信息拷贝到管道中
  3. 用户端将管道中的信息拷贝到用户端的缓冲区中
  4. 将用户端临时缓冲区的信息拷贝到输出文件中

再来看看共享内存通信:

image-20231118163302563

从这张图可以看出,使用共享内存进行通信,将一个文件从一个进程传输到另一个进程只需要进行两次拷贝操作:

  1. 从输入文件到共享内存。
  2. 从共享内存到输出文件。

从以往的 学习中,我们可以得知影响进程间通信时间最严重的是IO

所以共享内存是所有进程间通信方式中最快的一种通信方式,因为该通信方式需要进行的拷贝次数最少。但是共享内存也是有缺点的,我们知道管道是自带同步与互斥机制的,但是共享内存并没有提供任何的保护机制,包括同步与互斥。

临界资源、临界区、原子性、互斥

  • 临界资源:

被多个进程能够同时看到的资源,叫做临界资源(管道,共享内存中的资源都属于临界资源)

如果没有对临界资源进行任何保护,对于临界资源的访问,双方进程在进行访问的时候,就会都是乱序的,可能会因为读写交叉而导致各种乱码、废弃数据、访问控制方面的问题。

  • 临界区:

对多个进程而言,访问临界资源的代码,叫做临界区。(在之前写的进程代码中,只有一部分代码会访问临界资源,这部分代码就叫做临界区)

  • 原子性:

我们把一件事情,要么没做,要么做完了,称之为原子性

  • 互斥:

缓冲区的信息拷贝到输出文件中

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

进程间通信 的相关文章

  • Java Runtime.getRuntime().freeMemory() 问题

    我搜索并看到了一些线程 但没有一个能够解决我遇到的具体问题 我正在尝试使用以下方式监视我的内存使用情况Runtime getRuntime freeMemory Runtime getRuntime maxMemory and Runtim
  • Spring Security 自定义过滤器

    我想自定义 Spring security 3 0 5 并将登录 URL 更改为 login 而不是 j spring security check 我需要做的是允许登录 目录并保护 admin report html 页面 首先 我使用教
  • @RestController 没有 @ResponseBody 方法工作不正确

    我有以下控制器 RestController RequestMapping value base url public class MyController RequestMapping value child url method Req
  • 使用 Ant 将非代码资源添加到 jar 文件

    我正在将 java 应用程序打包成 jar 文件 我正在使用 ant 和 eclipse 我实际上需要在 jar 中直接在根文件夹下包含几个单独的非代码文件 xml 和 txt 文件 而不是与代码位于同一位置 我正在尝试使用includes
  • “java.net.MalformedURLException:未找到协议”读取到 html 文件

    我收到一个错误 java net MalformedURLException Protocol not found 我想读取网络上的 HTML 文件 mainfest uses permission android name android
  • nginx 上的多个网站和可用网站

    通过 nginx 的基本安装 您的sites available文件夹只有一个文件 default 怎么样sites available文件夹的工作原理以及如何使用它来托管多个 单独的 网站 只是为了添加另一种方法 您可以为您托管的每个虚拟
  • 不同类型的数组

    是否可以有一个包含两种不同类型数据的数组 我想要一个包含双精度型和字符串的数组 我尝试过 ArrayList
  • 是否可以使用 Flying Saucer (XHTML-Renderer) 将 css 解析为类路径资源?

    我正在尝试将资源打包到 jar 中 但我无法让 Flying Saucer 在类路径上找到 css 我无法轻松构建 URL 来无缝解决此问题 https stackoverflow com questions 861500 url to l
  • 需要使用 joda 进行灵活的日期时间转换

    我想使用 joda 解析电子邮件中的日期时间字符串 不幸的是我得到了各种不同的格式 例如 Wed 19 Jan 2011 12 52 31 0600 Wed 19 Jan 2011 10 15 34 0800 PST Wed 19 Jan
  • Jackson XML ArrayList 输出具有两个包装器元素

    我在 Jackson 生成的 XML 输出中得到了两个包装器元素 我只想拥有一个 我有一个 Java bean Entity Table name CITIES JacksonXmlRootElement localName City pu
  • 自动生成Flyway的迁移SQL

    当通过 Java 代码添加新模型 字段等时 JPA Hibernate 的自动模式生成是否可以生成新的 Flyway 迁移 捕获自动生成的 SQL 并将其直接保存到新的 Flyway 迁移中 以供审查 编辑 提交到项目存储库 这将很有用 预
  • 如何检测 Java 字符串中的 unicode 字符?

    假设我有一个包含 的字符串 我如何找到所有这些 un icode 字符 我应该测试他们的代码吗 我该怎么做呢 例如 给定字符串 A X 我想将其转换为 AYXY 我想对其他 unicode 字符做同样的事情 并且我不想将它们存储在某种翻译映
  • 了解joda时间PeriodFormatter

    我以为我明白了 但显然我不明白 你能帮我通过这些单元测试吗 Test public void second assertEquals 00 00 01 OurDateTimeFormatter format 1000 Test public
  • 如何在 Spring 属性中进行算术运算?

  • 使用 Mockito 模拟某些方法,但不模拟其他方法

    有没有办法使用 Mockito 模拟类中的某些方法 而不模拟其他方法 例如 在这个 诚然是人为的 Stock我想嘲笑的班级getPrice and getQuantity 返回值 如下面的测试片段所示 但我想要getValue 执行乘法 如
  • java库维护数据库结构

    我的应用程序一直在开发 所以偶尔 当版本升级时 需要创建 更改 删除一些表 修改一些数据等 通常需要执行一些sql代码 是否有一个 Java 库可用于使我的数据库结构保持最新 通过分析类似 db structure version 信息并执
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 如何重新启动死线程? [复制]

    这个问题在这里已经有答案了 有哪些不同的可能性可以带来死线程回到可运行状态 如果您查看线程生命周期图像 就会发现一旦线程终止 您就无法返回到新位置 So 没有办法将死线程恢复到可运行状态 相反 您应该创建一个新的 Thread 实例
  • 将 Apache Camel 执行器指标发送到 Prometheus

    我正在尝试转发 添加 Actuator Camel 指标 actuator camelroutes 将交换 交易数量等指标 发送到 Prometheus Actuator 端点 有没有办法让我配置 Camel 将这些指标添加到 Promet
  • 泛型、数组和 ClassCastException

    我想这里一定发生了一些我不知道的微妙事情 考虑以下 public class Foo

随机推荐

  • 构建免费的Dokan和WooCommerce构建线上课程市场在线销售数字课程

    我们知道创建良好的学习说明和材料很困难 但当涉及到销售时 就变得更加困难 如果您无法出售您的课程 那么没有什么比这更令人沮丧的了 幸运的是 如果您使用的是 WordPress 网站 那么您可以非常轻松且免费地完成此操作 借助LearnPre
  • 工业异常检测AnomalyGPT-Demo试跑

    写在前面 如果你有大的cpu和gpu可以使用 直接根据官方的安装说明就可以 如果没有 可以点进来试着看一下我个人的安装经验 一 试跑环境 NVIDIA4090显卡24g cpu内存33G 交换空间8g 操作系统ubuntu22 04 试跑过
  • vue的组件

    在Vue中 组件是可复用的代码块 用于构建用户界面 Vue的组件系统允许您将界面拆分为独立的 可重复使用的部件 提供了更好的代码组织和复用性 以下是在Vue中创建组件的基本步骤 创建一个组件实例 可以使用Vue extend 方法创建一个V
  • 20个精彩的WordPress会员网站案例

    点击查看原文 对在线社区和独家内容的需求正在迅速增长 这就是WordPress 会员网站 发挥作用的地方 它为网站主提供了一个强大的平台 让他们可以创建有吸引力的社区 同时通过内容获利 无论您是倾向于提供免费会员还是旨在释放盈利的全部潜力
  • 毕设开题分享 yolo深度学习动物识别

    文章目录 0 前言 1 深度学习实现动物识别与检测 2 卷积神经网络 2 1卷积层 2 2 池化层 2 3 激活函数 2 4 全连接层 2 5 使用tensorflow中keras模块实现卷积神经网络
  • 「HDLBits题解」Gates4

    本专栏的目的是分享可以通过HDLBits仿真的Verilog代码 以提供参考 各位可同时参考我的代码和官方题解代码 或许会有所收益 题目链接 Gates4 HDLBits module top module input 3 0 in out
  • uni.ownloadFile下载下来的文件没有后缀名

    let filepathss plus io convertLocalFileSystemURL data tempFilePath plus io resolveLocalFileSystemURL filepathss function
  • python ConfigParser:Python 标准库,ini 文件解析器

    2024软件测试面试刷题 这个小程序 永久刷题 靠它快速找到工作了 刷题APP的天花板 大家好 在进行接口自动化工作时 配置文件是非常常见和重要的一部分 Python 提供了一个强大的标准库 ConfigParser 用于解析和处理 INI
  • Java版商城:Spring Cloud+SpringBoot b2b2c实现多商家入驻直播带货及 免 费 小程序商城搭建的完整指南

    随着互联网的快速发展 越来越多的企业开始注重数字化转型 以提升自身的竞争力和运营效率 在这个背景下 鸿鹄云商SAAS云产品应运而生 为企业提供了一种简单 高效 安全的数字化解决方案 鸿鹄云商SAAS云产品是一种基于云计算的软件服务 旨在帮助
  • java版商城之一件代发设置 Spring Cloud+SpringBoot+mybatis+uniapp b2b2c o2o 多商家入驻商城免 费 搭 建 直播带货商城

    在数字化时代 电商行业正经历着前所未有的变革 鸿鹄云商的saas云平台以其独特的架构和先进的理念 为电商行业带来了全新的商业模式和营销策略 该平台涉及多个平台端 包括平台管理 商家端 买家平台 微服务平台等 涵盖了pc端 手机端 h5 公众
  • 从外卖员到程序员,自学3年终于转行成功,三面“拿下”拼多多

    前言 先来自我介绍 老家农村 家里好不容易把我送到大城市读书 大学非985 211 但在我们老家 能出一个本科大学生也是非常不容易的 因为农村信息的相对闭塞 我对大学专业一无所知 加上分数并非前茅 最后被调剂一个我并不喜欢的专业 这里就不透
  • 所有行业的最终归宿-知识付费saas租户平台 打造知识付费平台

    随着科技的不断进步和全球化的加速发展 我们生活在一个信息爆炸的时代 各行各业都在努力适应这一变化 寻找新的商业模式和增长机会 在这个过程中 一个趋势逐渐凸显出来 那就是知识付费 可以说 知识付费正在成为所有行业的最终归宿 明理信息科技知识服
  • HarmonyOS鸿蒙开发指南:容器组建 form开发指导

    目录 创建Form组件 实现表单缩放 设置Form样式 添加响应事件 场景示例 创建Form组件 在pages index目录下的hml文件中创建一个Form组件 div class container div
  • HarmonyOS鸿蒙开发指南:容器组建 stepper开发指导

    目录 创建Stepper组件 设置index属性 设置样式 添加事件 场景示例 创建Stepper组件 在pages index目录下的hml文件中创建一个Stepper组件 div class container div
  • Java 学习路线 2024 最新版!

    又对上次分享的 Java 学习路线进行了简单修改完善 并增加了免登录下载和黑夜模式 这里重发一下 花了一个月零碎的时间 我根据当下 Java 后端求职和招聘的最新要求 对之前写的 Java 后端学习路线进行了全面的优化和改进 添加图片注释
  • 【银行测试】金融项目-APP测试要点详细汇总(详全)

    目录 导读 前言 一 Python编程入门到精通 二 接口自动化项目实战 三 Web自动化项目实战 四 App自动化项目实战 五 一线大厂简历 六 测试开发DevOps体系
  • python画彩虹和小熊

    前言 今天 我们来画两个简单的图形 一 彩虹 彩虹 又称天弓 客家话 天虹 绛等 简称为 虹 是气象中的一种光学现象 当太阳光照射到半空中的水滴时 光线被折射及反射 在天空上形成拱形的七彩光谱 雨后常见 形状弯曲 通常为半圆状 色彩艳丽 东
  • react-native打包发布

    1 在命令行中使用以下命令生成签名密钥 keytool genkeypair v keystore my release key keystore alias my key alias keyalg RSA keysize 2048 val
  • HarmonyOS鸿蒙开发指南:容器组建 list开发指导

    创建List组件 在pages index目录下的hml文件中创建一个List组件 div class container div
  • 进程间通信

    进程间通信 进程间通信介绍 进程间通信目的 数据传输 一个进程需要将它的数据发送给另一个进程 资源共享 多个进程之间共享同样的资源 通知事件 一个进程需要向另一个或一组进程发送消息 通知它 它们 发生了某种事件 如进程终止 时要通知父进程