Linux 详谈进程间通信(二)

进程间通信---共享内存(Shared Memory) 共享内存的概念:共享内存是进程间通信(IPC)中最简单的方式之一,也是最快的IPC形式。共享内存允许两个或多个进程访问同一块内存。当一个进程改变了这块内存中的内容的时候,其他进程就可以察觉到这种更改。一旦这样的内存映射到共享它的进程的地址空间,这些进程间的数据传递将不再涉及到内核,即进程不再通过执行进入内核的系统调用来传递数据,而是这些进程通过共享内存来传递数据。共享内存的原理:共享内存就是有一块... 阅读详情

目录

1. 命名管道

创建⼀个命名管道

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

命名管道的打开规则

实例1. ⽤命名管道实现⽂件拷⻉

实例2. ⽤命名管道实现server&client通信

2. system V共享内存

共享内存⽰意图

共享内存函数

实例1. 共享内存实现通信

实例2. 借助管道实现访问控制版的共享内存

3. 内核是如何组织管理IPC资源的


1. 命名管道

管道应⽤的⼀个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。

如果我们想在不相关的进程之间交换数据,可以使⽤FIFO⽂件来做这项⼯作,它经常被称为命名管道。

命名管道是⼀种特殊类型的⽂件

创建⼀个命名管道

命名管道可以从命令⾏上创建,命令⾏⽅法是使⽤下⾯这个命令:

$ mkfifo filename

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

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

创建命名管道:

int main(int argc, char *argv[])
{
    mkfifo("p2", 0644);
    return 0;
}

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

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

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

FIFO(命名管道)与pipe(匿名管道)之间唯⼀的区别在它们创建与打开的⽅式不同,⼀但这些⼯作完成之后,它们具有相同的语义。

命名管道的打开规则

如果当前打开操作是为读⽽打开FIFO时

O_NONBLOCK disable:阻塞直到有相应进程为写⽽打开该FIFO

O_NONBLOCK enable:⽴刻返回成功

如果当前打开操作是为写⽽打开FIFO时

O_NONBLOCK disable:阻塞直到有相应进程为读⽽打开该FIFO

O_NONBLOCK enable:⽴刻返回失败,错误码为ENXIO

实例1. ⽤命名管道实现⽂件拷⻉

读取⽂件,写⼊命名管道

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main(int argc, char* argv[])
{
	mkfifo("tp", 0644);
	int infd;
	infd = open("abc", O_RDONLY);
	if (infd == -1) ERR_EXIT("open");
	int outfd;
	outfd = open("tp", O_WRONLY);
	if (outfd == -1) ERR_EXIT("open");
	char buf[1024];
	int n;
	while ((n = read(infd, buf, 1024)) > 0)
	{
		write(outfd, buf, n);
	}
	close(infd);
	close(outfd);
	return 0;
}

读取管道,写⼊⽬标⽂件:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main(int argc, char* argv[])
{
	int outfd;
	outfd = open("abc.bak", O_WRONLY | O_CREAT | O_TRUNC, 0644);
	if (outfd == -1) ERR_EXIT("open");
	int infd;
	infd = open("tp", O_RDONLY);
	if (outfd == -1)
		ERR_EXIT("open");
	char buf[1024];
	int n;
	while ((n = read(infd, buf, 1024)) > 0)
	{
		write(outfd, buf, n);
	}
	close(infd);
	close(outfd);
	unlink("tp");
	return 0;
}

实例2. ⽤命名管道实现server&client通信

# ll
total 12
-rw-r--r--. 1 root root 46 Sep 18 22:37 clientPipe.c
-rw-r--r--. 1 root root 164 Sep 18 22:37 Makefile
-rw-r--r--. 1 root root 46 Sep 18 22:38 serverPipe.c
# cat Makefile
.PHONY:all
all:clientPipe serverPipe
clientPipe:clientPipe.c
    gcc -o $@ $^
serverPipe:serverPipe.c
    gcc -o $@ $^
.PHONY:clean
clean:
    rm -f clientPipe serverPipe

-- serverPipe.c --

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#define ERR_EXIT(m) \
do{\
perror(m);\
exit(EXIT_FAILURE);\
}while(0)
int main()
{
	umask(0);
	if (mkfifo("mypipe", 0644) < 0) {
		ERR_EXIT("mkfifo");
	}
	int rfd = open("mypipe", O_RDONLY);
	if (rfd < 0) {
		ERR_EXIT("open");
	}
	char buf[1024];
	while (1) {
		buf[0] = 0;
		printf("Please wait...\n");
		ssize_t s = read(rfd, buf, sizeof(buf) - 1);
		if (s > 0) {
			buf[s - 1] = 0;
			printf("client say# %s\n", buf);
		}
		else if (s == 0) {
			printf("client quit, exit now!\n");
			exit(EXIT_SUCCESS);
		}
		else {
			ERR_EXIT("read");
		}
	}
	close(rfd);
	return 0;
}

-- clientPipe.c --

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define ERR_EXIT(m) \
do{\
perror(m);\
exit(EXIT_FAILURE);\
}while(0)
int main()
{
	int wfd = open("mypipe", O_WRONLY);
	if (wfd < 0) {
		ERR_EXIT("open");
	}
	char buf[1024];
	while (1) {
		buf[0] = 0;
		printf("Please Enter# ");
		fflush(stdout);
		ssize_t s = read(0, buf, sizeof(buf) - 1);
		if (s > 0) {
			buf[s] = 0;
			write(wfd, buf, strlen(buf));
		}
		else if (s <= 0) {
			ERR_EXIT("read");
		}
	}
	close(wfd);
	return 0;
}

2. system V共享内存

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

共享内存⽰意图

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 byDIPC */
	void shm_unused3; /* unused*/
};

共享内存函数

shmget函数

功能:⽤来创建共享内存
原型
int shmget(key_t key, size_t size, int shmflg);
参数
    key:这个共享内存段名字
    size:共享内存⼤⼩
    shmflg:由九个权限标志构成,它们的⽤法和创建⽂件时使⽤的mode模式标志是⼀样的
取值为IPC_CREAT:共享内存不存在,创建并返回;共享内存已存在,获取并返回。
取值为IPC_CREAT | IPC_EXCL:共享内存不存在,创建并返回;共享内存已存在,出错返回。
返回值:成功返回⼀个⾮负整数,即该共享内存段的标识码;失败返回-1

shmat函数

功能:将共享内存段连接到进程地址空间
原型
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数
    shmid: 共享内存标识
    shmaddr:指定连接的地址
    shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回⼀个指针,指向共享内存第⼀个节;失败返回-1

说明:

shmaddr为NULL,核⼼⾃动选择⼀个地址

shmaddr 不为 NULL 且 shmflg ⽆ SHM_RND 标记,则以 shmaddr 为连接地址。
shmaddr 不为 NULL 且 shmflg 设置了 SHM_RND 标记,则连接的地址会⾃动向下调整 SHMLBA 的整数倍。
公式: shmaddr - (shmaddr % SHMLBA)
shmflg=SHM_RDONLY ,表⽰连接操作⽤来只读共享内存

shmdt函数

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

shmctl函数

功能:⽤于控制共享内存
原型
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数
    shmid:由shmget返回的共享内存标识码
    cmd:将要采取的动作(有三个可取值)
    buf:指向⼀个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1

实例1. 共享内存实现通信

测试代码结构

# ls
client.c comm.c comm.h Makefile server.c
# cat Makefile
.PHONY:all
all:server client
client:client.c comm.c
    gcc -o $@ $^
server:server.c comm.c
    gcc -o $@ $^
.PHONY:clean
clean:
    rm -f client server

-- comm.h --

#ifndef _COMM_H_
#define _COMM_H_
# include <stdio.h>
# include <sys/types.h>
# include <sys/ipc.h>
# include <sys/shm.h>
# define PATHNAME "."
# define PROJ_ID 0x6666
int createShm(int size);
int destroyShm(int shmid);
int getShm(int size);
# endif

-- comm.c --

#include "comm.h"
static int commShm(int size, int flags)
{
	key_t key = ftok(PATHNAME, PROJ_ID);
	if (key < 0) {
		perror("ftok");
		return -1;
	}
	int shmid = 0;
	if ((shmid = shmget(key, size, flags)) < 0) {
		perror("shmget");
		return -2;
	}
	return shmid;
}
int destroyShm(int shmid)
{
	if (shmctl(shmid, IPC_RMID, NULL) < 0) {
		perror("shmctl");
		return -1;
	}
	return 0;
}
int createShm(int size)
{
	return commShm(size, IPC_CREAT | IPC_EXCL | 0666);
}
int getShm(int size)
{
	return commShm(size, IPC_CREAT);
}

-- server.c --

#include "comm.h"
int main()
{
	int shmid = createShm(4096);
	char* addr = shmat(shmid, NULL, 0);
	sleep(2);
	int i = 0;
	while (i++ < 26) {
		printf("client# %s\n", addr);
		sleep(1);
	}
	shmdt(addr);
	sleep(2);
	destroyShm(shmid);
	return 0;
}

-- client.c --

#include "comm.h"
int main()
{
	int shmid = getShm(4096);
	sleep(1);
	char* addr = shmat(shmid, NULL, 0);
	sleep(2);
	int i = 0;
	while (i < 26) {
		addr[i] = 'A' + i;
		i++;
		addr[i] = 0;
		sleep(1);
	}
	shmdt(addr);
	sleep(2);
	return 0;
}

ctrl+c终⽌进程,再次重启

# ./server
shmget: File exists
# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x66026a25 688145 root 666 4096 0
# ipcrm -m 688145 #删除shm ipc资源,注意,不是必须通过⼿动来删除,这⾥只为演⽰相关指令,删除IPC资源是进程该做的事情

bytes 和 nattch 有时间可以研究⼀下

注意:共享内存没有进⾏同步与互斥! 共享内存缺乏访问控制!会带来并发问题。

实例2. 借助管道实现访问控制版的共享内存

-- Comm.hpp -- 

#pragma once
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <cassert>
#include <cstdio>
#include <ctime>
#include <cstring>
#include <iostream>
using namespace std;
#define Debug 0
#define Notice 1
#define Warning 2
#define Error 3
const std::string msg[] = {
"Debug",
"Notice",
"Warning",
"Error"
};
std::ostream& Log(std::string message, int level)
{
	std::cout << " | " << (unsigned)time(nullptr) << " | " << msg[level] << "
		| " << message;
		return std::cout;
}
#define PATH_NAME "/home/hyb"
#define PROJ_ID 0x66
#define SHM_SIZE 4096 // 共享内存的⼤⼩,最好是⻚(PAGE: 4096)的整数倍
#define FIFO_NAME "./fifo"
class Init {
public:
	Init() {
		umask(0);
		int n = mkfifo(FIFO_NAME, 0666);
		assert(n == 0);
		(void)n;
		Log("create fifo success", Notice) << "\n";
	}
	~Init() {
		unlink(FIFO_NAME);
		Log("remove fifo success", Notice) << "\n";
	}
};
#define READ O_RDONLY
#define WRITE O_WRONLY
int OpenFIFO(std::string pathname, int flags) {
	int fd = open(pathname.c_str(), flags);
	assert(fd >= 0);
	return fd;
}
void CloseFifo(int fd) {
	close(fd);
}
void Wait(int fd) {
	Log("等待中....", Notice) << "\n";
	uint32_t temp = 0;
	ssize_t s = read(fd, &temp, sizeof(uint32_t));
	assert(s == sizeof(uint32_t));
	(void)s;
}
void Signal(int fd) {
	uint32_t temp = 1;
	ssize_t s = write(fd, &temp, sizeof(uint32_t));
	assert(s == sizeof(uint32_t));
	(void)s;
	Log("唤醒中....", Notice) << "\n";
}
string TransToHex(key_t k) {
	char buffer[32];
	snprintf(buffer, sizeof buffer, "0x%x", k);
	return buffer;
}

-- ShmServer.cc --

#include "Comm.hpp"
Init init;
int main() {
	// 1. 创建公共的Key值
	key_t k = ftok(PATH_NAME, PROJ_ID);
	assert(k != -1);
	Log("create key done", Debug) << " server key : " << TransToHex(k) << endl;
	// 2. 创建共享内存 -- 建议要创建⼀个全新的共享内存 -- 通信的发起者
	int shmid = shmget(k, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);
	if (shmid == -1) {
		perror("shmget");
		exit(1);
	}
	Log("create shm done", Debug) << " shmid : " << shmid << endl;
	// 3. 将指定的共享内存,挂接到⾃⼰的地址空间
	char* shmaddr = (char*)shmat(shmid, nullptr, 0);
	Log("attach shm done", Debug) << " shmid : " << shmid << endl;
	// 4. 访问控制
	int fd = OpenFIFO(FIFO_NAME, O_RDONLY);
	while (true) {
		// 阻塞
		Wait(fd);
		// 临界区
		printf("%s\n", shmaddr);
		if (strcmp(shmaddr, "quit") == 0)
			break;
	}
	CloseFifo(fd);
	// 5. 将指定的共享内存,从⾃⼰的地址空间中去关联
	int n = shmdt(shmaddr);
	assert(n != -1);
	(void)n;
	Log("detach shm done", Debug) << " shmid : " << shmid << endl;
	// 6. 删除共享内存,IPC_RMID即便是有进程和当下的shm挂接,依旧删除共享内存
	n = shmctl(shmid, IPC_RMID, nullptr);
	assert(n != -1);
	(void)n;
	Log("delete shm done", Debug) << " shmid : " << shmid << endl;
	return 0;
}

-- ShmClient.cc --

#include "Comm.hpp"
int main() {
	// 1. 创建公共的Key值
	key_t k = ftok(PATH_NAME, PROJ_ID);
	if (k < 0) {
		Log("create key failed", Error) << " client key : " << TransToHex(k)<< endl;
		exit(1);
	}
	Log("create key done", Debug) << " client key : " << TransToHex(k) << endl;
	// 2. 获取共享内存
	int shmid = shmget(k, SHM_SIZE, 0);
	if (shmid < 0) {
		Log("create shm failed", Error) << " client key : " << TransToHex(k)
			<< endl;
		exit(2);
	}
	Log("create shm success", Error) << " client key : " << TransToHex(k) <<endl;
	// 3. 挂接共享内存
	char* shmaddr = (char*)shmat(shmid, nullptr, 0);
	if (shmaddr == nullptr) {
		Log("attach shm failed", Error) << " client key : " << TransToHex(k)<< endl;
		exit(3);
	}
	Log("attach shm success", Error) << " client key : " << TransToHex(k) <<endl;
	// 4. 写
	int fd = OpenFIFO(FIFO_NAME, O_WRONLY);
	while (true) {
		ssize_t s = read(0, shmaddr, SHM_SIZE - 1);
		if (s > 0) {
			shmaddr[s - 1] = 0;
			Signal(fd);
			if (strcmp(shmaddr, "quit") == 0)
				break;
		}
	}
	CloseFifo(fd);
	// 5. 去关联
	int n = shmdt(shmaddr);
	assert(n != -1);
	Log("detach shm success", Error) << " client key : " << TransToHex(k) <<endl;
	return 0;
}

3. 内核是如何组织管理IPC资源的

这一看一些图

Linux进程间通信机制详谈 Linux进程间通信机制 Unix系统提供的进程间通信机制主要有: 管道和FIFO(命名管道) 套接字 信号 信号量 消息队列 共享内存区 管道pipe 管道机制思想是在内存中创建一个共享文件,从而使得通信双方利用该共享文件进行交互。需要注意的是管道数据流动是单向的,是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道。管道只在具有公共祖先的两个进程之间使用,可以将管道视为一个独立的文件系统,管道在管道两侧的进程看来就是一个文件,只是这个文件只存在于内存中。 一个进程写入管道的所有数 阅读详情

相关推荐

Linux——进程间通信

之前写的代码都是单进程的。是无法使用并发能力,并且无法实现多进程协同传输数据,同步执行流,消息通知等进程间通信不是目的,而是一种手段。进程间通信的技术背景进程是具有独立性的。虚拟地址空间+页表。保证进程运行的独立性(进程内核数据结构+进程的代码和数据)通信成本比较高。如何理解进程间通信?进程运行具有独立性!——进程想通信,难度比较大——进程间通信的本质:需要中间媒介,先让不同的进程看到同一份资源(内存空间)所谓的进程看到同一块“内存”,属于哪一个进程?

Ll_R_lL的博客 3857

【Linux】进程间通信 —— System V

一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再设计到内核,换句话说进程不再通过执行进入内核的系统调用来传递数据了。SHM_RND标志,则连接的地址会自动向下调整为SHMLBA的整数倍。注意:共享内存段不是必须手动删除,这里只是演示,应该由进程删除IPC资源。shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY。返回值:成功返回一个非负整数,即该共享内存段的标识码;注意:将共享内存段与当前进程脱离并不表示删除该共享内存段。shmid:由shmget返回的共享内存标识码。

2401_82759674的博客 634

【Linux】进程间通信

主要介绍了进程间通信的方式:管道(匿名管道,命名管道);共享内存,附有实现代码

2302_76941579的博客 2160

【Linux学习笔记】进程间通信之共享内存

本文介绍了Linux进程间通信中的共享内存机制。主要内容包括System V共享内存的原理、数据结构和相关函数(shmget、shmat、shmdt、shmctl)的使用方法。通过示例代码演示了客户端和服务器端如何通过共享内存实现通信,并提出了借助管道实现访问控制的改进方案。共享内存是Linux中高效的IPC方式,可以实现进程间的快速数据交换。文章还提供了详细的代码实现,包括共享内存的创建、连接、读写和销毁过程。

大白的编程日记. 716

Linux 进程间通信

Linux进程通信继承了传统的UNIX进程间通信方式,包括无名管道、有名管道以及信号;还有System V进程间通信(IPC),包括System V消息队列、System V信号量以及System V共享内存;套接字。

分享 3116

无线Mesh组网全攻略:从原理、部署到调优与排障

对于布线困难的大户型、复式楼或园区,传统的无线中继往往面临带宽减半和链路不稳定的问题。无线Mesh网络通过多跳转发与自组织路由,让每个节点无需网线即可协作扩展覆盖,并依靠动态路径选择实现自愈。其核心技术涉及802.11s、HWMP路由协议,以及802.11k/v/r协同的无缝漫游,能有效提升终端切换体验。在实际部署中,设备选型、回程频段规划与布点位置直接决定网络质量。围绕无线Mesh的组网原理、设备选型、配置调优与故障排查,提供一套工程实践参考,帮助用户在复杂环境下构建稳定高效的无缝覆盖。

weixin_34098209的博客 270

system V IPC :共享内存,消息队列与信号量(详解)

本文详细介绍了system V IPC中的共享内存,通过实例帮助大家深入理解这种通信方式。同时,对消息队列和信号量也做了比较详细的介绍,引入了共享资源,临界资源,临界区,同步,互斥等一批概念。

Miun123的博客 4049

逆向小记 bd-ticket-guard-client-cert | bd-ticket-guard-client-data 通过现象看本质

依然没什么花哨的直接解析出来,既然这是个X509证书,那么要么是服务器下发,要么是自己生成喽,但是如果是本地直接生成,那服务器还校验个鬼哦!既然是服务器下发的,那服务器又是怎么校验这个证书是自己下发的呢,这就要讲到CA验证了,首先根据上图我们发现证书的Issuer"(颁发者)是。怎么来的呢,因为涉及到逆向咱就不讲了,其实也是涉及到非对称加密的,就是客户端用私钥去签名数据,服务器用上传过去的证书公钥验签的过程!当服务器收到这个证书的时候,会做几件事,首先用自己的公钥解开签名获得解密后的证书hash。

2503_90751789的博客 1205

Linux进程间通信

进程间通信(IPC)是指不同进程之间的数据交换和通信。在多进程环境下,不同的进程需要共享内存、文件等资源,但是每个进程都有自己独立的地址空间,因此需要通过进程间通信来实现进程之间的数据交换和共享。进程间通信使得进程间可以进行数据传输、资源共享、通知事件等。例如,一个进程需要将它的数据发送给另一个进程,或者多个进程之间共享同样的资源,或者一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件等。本节我们将为大家介绍进程间通信的相关知识!

ARMCSKGT的博客 2752

SAP PP未清生产订单关闭物料退料、新工单发料批量处理

( werks = '1001' lgort = 'A004' lgobe = '组装-成品组装' )( werks = '1002' lgort = 'C006' lgobe = '组装-二车间' )( werks = '1002' lgort = 'C007' lgobe = '组装-二车间' )( werks = '1001' lgort = 'A007' lgobe = '组装-MS' )( werks = '1001' lgort = 'A008' lgobe = '组装-GW' )

dingqing86的专栏 1192

Hierarchical-Localization 环境配置与依赖管理全攻略

本文提供了Hierarchical-Localization(hloc)视觉定位工具箱从零开始的环境配置与依赖管理全攻略。针对Windows、Ubuntu和macOS三大操作系统,详细解析了Python版本选择、PyTorch与CUDA版本匹配、pycolmap版本锁定等核心依赖的安装步骤,并汇总了权重文件格式、NumPy版本、路径配置等常见问题的排查与解决方案,旨在帮助用户高效搭建稳定的hloc开发环境。

weixin_29066781的博客 335

【Linux进程间通信】Linux匿名管道详解:构建进程间通信的隐形桥梁

当提及Linux系统中的进程间通信(IPC),管道(Pipes)无疑是最基础且广泛使用的一种机制。作为匿名通信的典范,管道为进程间数据交换提供了一个简单而有效的途径。在这个信息飞速传递的时代,掌握Linux管道的使用不仅是理解操作系统底层通信原理的关键一步,也是提升软件开发效率、构建复杂应用系统的必备技能

EterNity_TiMe_的计算机学习之路 4088

FPGA实战:从零构建eMMC控制器(Verilog篇)

本文详细介绍了如何使用Verilog从零构建FPGA上的eMMC控制器,涵盖eMMC接口基础、命令系统解析、关键模块设计及性能优化技巧。通过实战案例,帮助开发者掌握高速数据存储解决方案,提升嵌入式系统开发能力。

weixin_26802933的博客 297

Linux 详谈进程间通信(一)

本文介绍了进程间通信(IPC)的概念和实现方式,重点讲解了管道通信机制。主要内容包括:进程间通信的目的(数据传输、资源共享、通知事件、进程控制)、发展历程及分类;管道的基本概念和原理,详细分析了匿名管道的创建、使用和实现机制;通过实例代码演示了管道读写操作,包括父子进程间通信;展示了使用管道创建进程池处理任务的完整实现方案;总结了管道通信的特点和限制(仅适用于亲缘进程、半双工、流式服务等)。文章还深入探讨了管道在内核层面的实现本质,以及在不同场景下的读写规则和行为表现。

yuzhaokangcode的博客 962

Kettle 连接 Oracle 数据库全流程指南

例如:C:\Oracle\product\19.0.0\dbhome_1\jdbc\lib\ojdbc8.jar 2. 替换 Kettle 驱动文件 将驱动文件复制到 Kettle 的 目录: 删除旧版本驱动:如 ojdbc14.jar 只能保留一个oracle驱动 重启 Kettle 以加载新驱动 二、配置数据库连接 1. 启动 Kettle 并新建转换 运行 (Windows)或 (Linux)。 新建转换(Transformation),添加 “表输入” 步骤,双击进入配置。 2.

qq_44724453的博客 3480

LED灯闪烁实验:实验介绍

每个章节都会单独进行验证工作,例如Simulink开发的应用层软件,会在Simulink-TestHarness中进行仿真,通过Scope示波器模块输出0-1交替的结果。CubeIDE集成双方的代码后,会烧写到开发板中验证是否按照定义的时间进行闪烁。ST-LINK V2是STM32开发生态系统中常用的硬件调试接口,能够连接微控制器与开发环境,实现程序的下载、调试和分析。STM32F103C8T6最小系统板是基于STM32F103C8T6微控制器的开发板,本实验会涉及使用板载的连接PC13引脚的LED灯。

u013288925的博客 457

Linux:进程间通信

一篇带你完全掌握进程间通信

Makise的博客 2098

Qt CEF融合技QCefView使用教程

如果从事C++客户端开发,对CEF应该不陌生,当C++界面需要和web交互时,CEF是很好的解决方案,当然Qt也提供了QWebEngineView来进行web交互,最近在万兴喵影的安装目录看到了QCefView.dll,之前也听说过这个库,没在意,没想到还真有人用到项目里面,于是决定自己编译写个demo看看......

琅嬛福地 1万+

<Linux> 进程间通信

进程间通信,匿名管道、命名管道、共享内存、消息队列、信号量

prodigy623的博客 3481

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

【linux】进程间通信(二)命名管道,mkfifo

一、命名管道原理 二、命名管道的特征 三、命名管道的情况 四、接口mkfifo 五、命名管道编码实现 函数接口mkpipe介绍 框架介绍 makefile comm.hpp server.cc client.cc 测试

重铸自身根基的博客 1496

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Linux之进程间通信

Linux之进程通信

2302_81120572的博客 1942

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Linux系统-进程间通信

本章主要讲解学习Linux中本系统下的进程间通信概念:进程间通信简称IPC(Inter process communication),进程间通信就是在不同进程之间传播或交换信息进程间通信目的:数据传输:一个进程需要将它的数据发送给另一个进程资源共享:多个进程之间共享同样的资源通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)

~ 4027

Linux: 进程间通信

在我们学习进程的时候,我们知道正是因为程序地址空间的存在,所以进程之间具有独立性,他们互不影响,但是在我们的实际应用中,进程之间总会有需要通信(交流获取对方数据)。

2301_79927432的博客 2822

【Linux】10. 进程间通信

本文讲述了4种进程间通信的手段:管道(匿名管道和命名管道)、System V标准下的3种通信方式(共享内存、消息队列和信号量)。无论是哪种进程间通信方式,本质上都是由操作系统提供一个公共空间作为桥梁,多个进程之间在这片公共空间上进行读写操作,以此来达成进程间通信的目的。

weixin_52811588的博客 2352
上一篇: Linux 详谈进程间通信(一)
下一篇: Linux 详谈Linux进程信号(一)
万我.
博客等级 码龄1年 460粉丝 93原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值