【IPC-UNIX网络编程】第4章管道和FIFO

2023-11-17

1. 一个简单的客户—服务器例子

  • Client从标准输入(stdin)读进一个路径名,并把它写入IPC通道。Server从该IPC通道读出这个路径名,并尝试打开其文件。若server能打开该文件,它能读出其中的内容,并写入(不一定同一个)IPC通道,以作为对客户的响应;否则响应一个错误信息。

在这里插入图片描述

2. 管道

管道由pipe函数创建,提供一个单向数据流。

  • 该函数返回2个文件描述符:fd[0]和fd[1]。前者读,后者写。【半双工】
  • 也可创建【全双工】IPC管道。(全双工:管道两端既可读又可写)
  • 【常见用途:shell】
#include <unistd.h>
int pipe(int fd[2]);  // 成功则返回0,否则返回-1
单进程中的管道与单进程内的管道
  • 单进程中的管道
    在这里插入图片描述
  • 单进程内的管道
    管道的典型用途是为两个不同进程(父进程、子进程)提供进程间的通信手段。
    1)一个进程(父进程)创建一个管道后调用fork派生一个子进程,接着父进程关闭这个管道的读出端,子进程关闭统一管道的写入端。

3 例子

  • main函数创建两个管道并用fork生成一个子进程。客户作为父进程运行,服务器作为子进程运行。第一个管道用于从客户向服务器发送路径名;第二个管道用于从服务器向客户发送该文件的内容。【每个文件描述符只负责读或写】
    在这里插入图片描述
#include "unpipc.h"
void client(int, int), server(int, int);

void client (int readfd, int writefd) {
	size_t len;
	ssize_t n;
	char buff[MAXLINE];
	Fgets(buff, MAXLINE, stdin);  // read pathname
	len = strlen(buff);  // fgets()以空字节作为其结尾
	if (buff[len-1] == '\n')
		len--;     // delete newline from fgets()
	Write(writefd, buff, len);  // write pathname to IPC channel
	while ( (n = Read(readfd, buff, MAXLINE)) > 0)
		Write(STDOUT_FILENO, buff, n);
}

void server (int readfd, int writefd) {
	int fd;
	ssize_t n;
	char buff[MAXLINE+1];
	// read pathname from IPC channel
	if ( (n = Read(readfd, buff, channel)) == 0)
		err_quit("end-of-file while reading pathname");
	buff[n] = '\0';

	// 打开所请求的文件读
	// 若出错则返回出错字符串
	if ( (fd = open(buff, O_RDONLY)) < 0) {
		snprintf(buff + n, sizeof(buff) - n, ": can't open, %s\n", strerror(errno));
		n = strlen(buff);
		Write(writefd, buff, n);
	} else {  // 若成功,则将文件内容复制到管道中
		// open succeeded: copy file to IPC channel
		while ( (n = Read(fd, buff, MAXLINE)) > 0)
			Write(writefd, buff, n);
		Close(fd);
	}
}

int main(int argc, char const *argv[])
{
	int pipe1[2], pipe2[2];
	pid_t childpid;
	Pipe(pipe1);  // create 2 pipes
	Pipe(pipe2);  // create 2 pipes

	if ( (childpid = Fork()) == 0) {  // child
		Close(pipe1[1]); // 子进程关闭pipe1的写端
		Close(pipe2[0]); // 子进程关闭pipe2的读端

	}
	// parent
	Close(pipe1[0]); // 父进程关闭pipe1的读端
	Close(pipe2[1]); // 父进程关闭pipe2的写端
	// 将pipe2[0]写进client,pipe1[0]读client
	client(pipe2[0], pipe1[1]);

	// 取得已终止子进程的终止状态
	Waitpid(childpid, NULL, 0);  // wait for child to terminate
	exit(0);

	return 0;
}

4 全双工管道的真正实现

  • 写入fd[1]的数据只能从fd[0]读出,写入fd[0]的数据只能从fd[1]读出。
    在这里插入图片描述

  • pipe(fd[2]),设置了client / server写入fd[1] / fd[0] 只能从 fd[0] / fd[1]读出。

    #include "unpipc.h"
    int main(int argc, char const *argv[])
    {
    	int fd[2], n;
    	char c;
    	pid_t childpid;
    	Pipe(fd);
    	if ( (childpid = Fork()) == 0 )	{
    		sleep(3);
    		if ( (n = Read(fd[0], &c, 1)) != 1) 
    			err_quit("child: read returned %d", n);
    		printf("child read %c\n", c);
    		Write(fd[0], "c", 1);
    		exit(0);			
    	}
    	Write(fd[1], "p", 1);
    	// 当server 并未往fd[0]写入数据时,此处发生阻塞
    	if ( (n = Read(fd[1], &c, 1)) != 1)
    		err_quit("child: read returned %d", n);
    	printf("parent read %c\n", c);
    	exit(0);
    	return 0;
    }
    

5 popen和pclose函数

popen函数创建一个管道并启动另外一个进程,该进程要么从该管道读出标准输入,要么往该管道写入标准输出

#include <stdio.h>
FILE *popen(const char *command, const char *type);  // 成功返回文件指针,否则返回NULL
int pclose(FILE *stream);  // 成功返回shell的终止状态,否则返回-1

command是shell命令行,PATH环境变量可用于定位command。popen在调用进程和所指定的命令之间创建一个管道。

  • 若type为r,则调用进程读进command的stdout
  • 若type为w,则调用进程写进command的stdin
例子:将客户-服务器使用popen()函数实现
#include "unpipc.h"
int main(int argc, char const *argv[])
{
	size_t n;
	char buff[MAXLINE], command[MAXLINE];
	FILE *fp;
	Fgets(buff, MAXLINE, stdin);
	n = strlen(buff);
	if (buff[n-1] == '\n')
		n--;
	snprintf(command, sizeof(command), "cat %s", buff);
	// command内容是路径名
	fp = Popen(command,"r");
	while (Fgets(buff, MAXLINE, fp) != NULL)
		Fputs(buff, stdout);
	Pclose(fp);
	exit(0);
}`在这里插入代码片`

6 FIFO

管道无名字,只能用于有一个共同祖先进程的各个进程之间,而无法在无亲缘关系的两个进程间创建一个管道并用作IPC通道。
FIFO称为有名管道,由mkfifo函数创建。

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);  // 成功则返回0,否则返回-1

mode参数指定文件权限位,类似于open的第二个参数

例子:使用两个FIFO代替两个管道

这个FIFO例子与之前的管道相比:

  • 创建并打开一个管道只需调用pipe。创建并打开一个FIFO则需在调用mkfifo后再调用open;
  • 管道在所有进程中最终都关闭它之后自动消失。FIFO的名字则只有通过调用unlink才从文件系统中删除。好处:FIFO在文件系统中有一个名字,该名字允许某个进程创建一个FIFO,与它无亲缘关系的另一个进程打开这个FIFO。
#include "unpipc.h"
// 在/tmp文件系统中创建2个FIFO。这2个FIFO事先存在与否无关紧要
#define FIFO1 "/tmp/fifo.1"
#define FIFO2 "/tmp/fifo.2"

void client(int, int), server(int, int);
int main(int argc, char const *argv[])
{
	int readfd, writefd;
	pid_t childpid;

	// create 2 FIFOs; OK if they already exist
	if ( (mkfifo(FIFO1, FILE_MODE) < 0) && (errno != EEXIST)) 
		err_sys("can't create %s", FIFO1);
	if ( (mkfifo(FIFO2, FILE_MODE) < 0) && (errno != EEXIST)) {
		unlink(FIFO1);
		err_sys("can't create %s", FIFO2)
	}
	if ( (childpid = Fork()) == 0) {
		readfd = Open(FIFO1, O_RDONLY, 0);
		writefd = Open(FIFO2, O_WRONLY, 0);		
		server(readfd, writefd);
		exit(0);
	}

	writefd = Open(FIFO1, O_WRONLY, 0);
	readfd = Open(FIFO2, O_RDONLY, 0);
	client(readfd, writefd);
	Waitpid(childpid, NULL, 0);  // wait for child to terminate
	Close(readfd);
	Close(writefd);

	Unlink(FIFO1);
	Unlink(FIFO2);
	exit(0);
}

如果对换父进程中两个open调用的顺序,该程序不工作。其原因在于,若当前尚无任何进程打开某个FIFO写,则打开该FIFO读的进程将阻塞。此时,父子进程都读,二者均阻塞,发生死锁现象。

Note:

  • 最后删除所用的FIFO的是client而不是server,因为对这些FIFO执行最终操作的是客户。
  • 内核为管道和FIFO维护一个访问计数器,其值是同一个管道或FIFO的打开着的描述符的个数。有了访问计数器后,client或server就能成功地调用unlink。尽管该函数从文件系统中删除了所指定的路径名,先前已经打开该路径名、目前仍打开着的描述符不受影响

7 管道和FIFO的额外属性

下面是关于管道或FIFO的读出与写入的若干额外规则:

  • 若请求写入的数据的字节数小于或等于PIPE_BUF,则write操作保证是原子的。即,若有两个进程差不多同时往管道或FIFO写,则或者先写入来自第一个进程的所有数据,再写入来自第二个进程的所有数据,或者颠倒。 系统不会相互混杂来自这两个进程的数据。然而,若请求写入的数据的字节数大于PIPE_BUF,则write操作不能保证是原子的。

8 单个服务器,多个客户

在这里插入图片描述

/tmp/fifo.serv为众所周知的路径名,服务器以此创建一个FIFO,它将从这个FIFO读入客户的请求。每个客户在启动时创建创建自己的FIFO,所用的路径名含有自己的进程ID。每个客户把自己的请求写入服务器的众所周知FIFO中,该请求含有客户的进程ID,以及一个路径名,具有该路径名的文件就是客户希望服务器打开并发回的文件。

8.1 服务器程序
#include "fifo.h"
void server(int, int);
int main(int argc, char const *argv[])
{
	int readfifo, writefifo, dummyfd, fd;
	char *ptr, buff[MAXLINE+1], fifoname[MAXLINE];
	pid_t pid;
	ssize_t n;
	if ( (mkfifo(SERV_FIFO, FILE_MODE) < 0) && (errno != EEXIST))
		err_sys("can't create %s", SERV_FIFO);
	readfifo = Open(SERV_FIFO, O_RDONLY, 0);  
	dummyfd = Open(SERV_FIFO, O_WRONLY, 0);  //never used

	while ( (n = Readline(readfifo, buff, MAXLINE)) > 0) {
		if (buff[n-1] == '\n')
			n--;
		buff[n] = '\0';
		if ( (ptr = strchr(buff, ' ')) == NULL) {
			err_sys("bogus request: %s", buff);
			continue;
		}
		// ptr增1后即指向后跟的路径名的首字符
		*ptr++ = 0;
		pid = atol(buff);
		snprintf(fifoname, sizeof(fifoname), "/tmp/fifo.%ld", (long)pid);
		// 尝试打开客户请求的文件
		if ( (writefifo = open(fifoname, O_WRONLY, 0)) < 0) {
			err_msg("cannot open: %s", fifoname);
			continue;
		}
		if ( (fd = open(ptr, O_RDONLY)) < 0) {
			snprintf(buff + n, sizeof(buff)-n, ":can't open, %s\n", 
				    strerror(errno));
			n = strlen(ptr);
			Write(writefifo, ptr, n);
			Close(writefifo);
		} else {
			while ( (n = Read(fd, buff, MAXLINE)) > 0)
				Write(writefifo, buff, n);
			Close(fd);
			Close(writefifo);
		}
	}
	exit(0);
}
8.2 客户端程序
#include "fifo.h"
int main(int argc, char const *argv[])
{
	int readfifo, writefifo;
	ssize_t n;
	size_t len;
	char *ptr, buff[MAXLINE], fifoname[MAXLINE];
	pid_t pid;
	pid = getpid();
	snprintf(fifoname, sizeof(fifoname), "/tmp/fifo.%ld", (long)pid);
	if ( (mkfifo(fifoname, FILE_MODE) < 0) && (errno != EEXIST))
		err_sys("can't create %s", fifoname);
	// start buffer with pid and a blank
	snprintf(buff, sizeof(buff), "%ld", (long)pid);
	len = strlen(buff);
	ptr = buff + len;
	// read pathname
	Fgets(ptr, MAXLINE-len, stdin);
	len = strlen(buff);
	// open FIFO to server and write PID and pathname to FIFO 
	writefifo = Open(SERV_FIFO, O_WRONLY, 0);  
	Write(writefifo, buff, len);
	// now open our FIFO; blocks until server opens for writing
	readfifo = Open(fifoname, O_RDONLY, 0);
	// read from IPC, write to standard output
	while ( (n = Read(readfifo, buff, MAXLINE)) > 0)
		Write(STDOUT_FILENO, buff, n);
	Close(readfifo);
	Unlink(fifoname);
	exit(0);
}

9 字节流与信息

  • 字节流I/O模型对读写操作不进行数据检查,例如,从某个FIFO中读出100字节的进程无法判断次100字节是执行了单个100字节的写操作,还是5个20字节的写操作,或者其他。
  • 有时候应用希望对所传送的数据加上某种结构,以知道获得信息的边界。下述3种技巧可用于这种目的:
    • 内特殊终止序列 :写进程给每个信息添加一个换行符,读进程则每次读出一行。
    • 显式长度;
  • mymesg结构
#include "unpipc.h"
// want sizeof(struct mymesg) <= PIPE_BUF
#define MAXMESGDATA (PIPE_BUF - 2*sizeof(long))
#define MESGHDRSIZE (sizeof(struct mymesg) - MAXMESGDATA)
struct mymesg {
	long mesg_len;   // can be 0
	long mesg_type;  // must be > 0
	char mesg_data[MAXMESGDATA];
};

ssize_t mesg_send(int, struct mymesg *);
void Mesg_send(int, struct mymesg *);
ssize_t mesg_recv(int, struct mymesg *);
ssize_t Mesg_recv(int, struct mymesg *);
  • mesg_send函数
ssize_t mesg_send(int fd, struct mymesg *mptr)
{
	return (write(fd, mptr, MESGHDRSIZE + mptr -> mesg_len));
}
  • mesg_recv函数
ssize_t mesg_recv(int fd, struct mymesg *mptr)
{
	size_t len;
	ssize_t n;

	// read message header first, to get len of data that follows
	if ( (n = Read(fd, mptr, MESGHDRSIZE)) == 0)
	// Note:return(0)是返回值为0, return 0 是终止程序
		return(0);
	else if (n != MESGHDRSIZE)
		err_quit("message header: expected %d, got%d", MESGHDRSIZE, n);

	if ( (len = mptr->mesg_len) > 0)
		if ( (n = Read(fd, mptr->mesg_data, len)) != len)
			err_quit("message data: expected %d, got %d", len, n);
	return(len);
}

10 习题

  • 4.2 我们一般是先调用mkfifo,检查是否返回EEXIST错误,若是则调用open。若先调用open,再调用mkfifo,情况又如何?

    如果调用关系反转了,另外某个进程就有可能在本进程的open和mkfifo两个调用之间创建本进程想要创建的FIFO,结果导致本进程的mkfifo调用失败。

  • 4.5 当服务器启动后,它阻塞在自己的第一个open调用中,直到客户的第一个open打开同一个FIFO用于写为止。我们怎样才能绕过这样的阻塞,使得两个open都立刻返回,转而阻塞正在首次调用readline上?

    把第一个open调用改为指定非阻塞标志 :
    readfifo = Open(SERV_FIFO, O_RDONLY | O_NONBLOCK, 0); 该调用将立即返回,接下去的open调用(用于只写)也立即返回,因为它要打开的FIFO已经由第一个open调用打开用于读。但是为了避免从readline返回错误,描述符readfifo的O_NONBLOCK标志必须在调用readline之前关掉。

  • 4.7 为什么在读进程关闭管道或FIFO之后给写进程产生一个信号,而不会在写进程关闭管道或FIFO之后给读进程产生一个信号?

    写进程关闭管道或FIFO的信息通过文件结束符传递给读进程。

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

【IPC-UNIX网络编程】第4章管道和FIFO 的相关文章

  • 如何使用不同的基本路径托管 Blazor WebAssembly 应用程序

    我有一个 Blazor Webassemble NET 托管应用程序 在我们托管它的服务器上 应用程序的基本路径将是mydomain com coolapp 因此 为了尝试让应用程序在服务器上正确呈现 我一直遵循本页 应用程序基本路径 部分
  • 非模板函数中的尾随返回类型[重复]

    这个问题在这里已经有答案了 我见过有人使用以下语法来实现函数 auto get next gt int 代替 int get next 我理解两者 并且我知道尾随返回类型语法对于使用 decltype 的模板代码很有用 就我个人而言 我会避
  • SOAP Web 服务:多台服务器,一个接口

    我有一个场景 需要任意数量的服务器来提供相同的 SOAP Web 服务 我想生成一组代理类 并能够为它们提供一个位置 以便在运行时将它们指向不同的服务器 不幸的是 看起来好像wsdl port节点 子节点wsdl service 要求对特定
  • 从结构调用 C++ 成员函数指针

    我找到了有关调用 C 成员函数指针和调用结构中的指针的信息 但我需要调用结构内部存在的成员函数指针 但我无法获得正确的语法 我在类 MyClass 的方法中有以下代码片段 void MyClass run struct int MyClas
  • 从图像创建半透明光标

    是否可以从图像创建光标并使其半透明 我目前正在拍摄自定义图像并覆盖鼠标光标图像 如果我可以将其设为半透明 那就太好了 但不是必需的 销售人员喜欢闪亮的 目前正在做这样的事情 Image cursorImage customImage Get
  • 注入包含接口的所有已注册实现的 Enumerable

    给出以下接口 public interface IMyProcessor void Process 我希望能够注册多个实现 并让我的 DI 容器将它们的可枚举注入到这样的类中 public class MyProcessorLibrary
  • ASP.NET - Crystal Report Viewer 打印按钮在 ASP.NET 中不起作用

    我正在使用 Visual Studio 2008 但我遇到了水晶报告问题 当我单击打印按钮时 它会将我带到弹出窗口 但未找到页面 弹出的网址是 http localhost aspnet client System Web 2 0 5072
  • 更改私有模块片段是否会导致模块重新编译?

    On 此页面有关 C 20 模块功能 https www modernescpp com index php c 20 modules private module fragment and header units 我发现了这样的说法 借
  • 如何在Windows窗体中打开进程

    我想在我的 Windows 窗体应用程序中打开进程 例如 我希望当用户按下 Windows 窗体容器之一中的按钮时 mstsc exe 将打开 如果他按下按钮 它将在另一个容器上打开 IE DllImport user32 dll SetL
  • 如何在VS2005中使用从.bat而不是.exe启动的外部程序进行调试?

    在我的 c 项目的调试属性中 我选择了 启动外部程序 并选择了我希望将调试器附加到的程序的 exe 但是 现在我需要从 bat 文件而不是 exe 启动程序 但 VS2005 似乎不允许这样做 这可能吗 编辑 为了澄清 我需要调试从 bat
  • C++网络序列化[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一种将 C 数据包序列化为网络流的解决方案 我在这里看到很多帖子提到人们 ACE 谷歌协议缓
  • 从单应性估计 R/T

    我一直在尝试计算 2 个图像中的特征 然后将这些特征传递回CameraParams R没有运气 特征已成功计算并匹配 但是问题是将它们传递回R t 我明白你必须分解Homography为了使这一点成为可能 我已经使用如下方法完成了 http
  • 为什么存在系统调用

    我一直在阅读有关系统调用及其在 Linux 中如何工作的内容 我还有更多的阅读要做 但我读过的一件事都没有回答 那就是 为什么我们需要系统调用 我知道系统调用是用户空间程序要求内核执行某些操作的请求 但我的问题基本上是 为什么用户空间程序本
  • 异步/等待 - 是*并发*吗?

    我一直在考虑 C 5 中新的异步内容 并且出现了一个特殊问题 据我了解 await关键字是一个简洁的编译器技巧 语法糖来实现连续传递 http en wikipedia org wiki Continuation passing style
  • 使用通用存储库模式和流畅的 nHibernate

    我目前正在开发一个中型应用程序 它将访问不同站点上的 2 个或更多 SQL 数据库等 我正在考虑使用类似的东西 http mikehadlow blogspot com 2008 03 using irepository pattern w
  • 稀疏矩阵超定线性方程组c/c++库

    我需要一个库来解决 Ax b 系统 其中 A 是一个非对称稀疏矩阵 每行有 8 个条目 而且可能很大 我认为实现双共轭梯度的库应该没问题 但我找不到一个有效的库 我尝试过 iml 但 iml sparselib 包中缺少一些标头 有小费吗
  • 如何将模型绑定到动态创建的类 nancyfx

    首先感谢任何愿意查看我的问题的人 我对 Nancyfx 还很陌生 在尝试将 JSON 有效负载绑定到动态创建的类时遇到问题 我按照这篇文章中的代码动态创建了该类 在C 中动态创建一个类 https stackoverflow com que
  • Centos/Linux 将 logrotate 设置为所有日志的最大文件大小

    我们使用 logrotate 并且它每天运行 现在我们遇到了一些情况 日志显着增长 阅读 gigabaytes 并杀死我们的服务器 所以现在我们想为日志设置最大文件大小 我可以将其添加到 logrotate conf 中吗 size 50M
  • NHibernate:无状态会话错误消息无法获取代理

    我正在使用 nHibernate 无状态会话来获取对象 更新一个属性并将对象保存回数据库 我不断收到错误消息 无状态会话无法获取代理 我在其他地方有类似的代码 所以我不明白为什么这不起作用 有谁知道问题可能是什么 我正在尝试更新Screen
  • 如何使用 Microsoft Graph API 更新 MailboxSettings

    我想从不同的日历更新邮箱设置 如何构建可以通过 Microsoft Graph 更新 MailboxSetting 的请求 这是我的代码示例 但有例外 代码示例 User obj GraphServiceClient Users roomC

随机推荐

  • STM32之NVIC

    STM32 Cortex M3 中NVIC 嵌套向量中断控制 的理解 一 STM32 Cortex M3 中的优先级概念 STM32 Cortex M3 中有两个优先级的概念 抢占式优先级和响应优先级 也把响应优先级称作 亚优先级 或 副优
  • jinfo如何使用

    jinfo是一个用于查看和调整Java虚拟机 JVM 配置参数的命令行工具 它可以在运行时获取和修改JVM的配置信息 包括内存分配 垃圾回收 运行时编译和其他设置 要使用jinfo 需要在命令行中输入以下命令 jinfo options
  • C# 学生成绩管理系统

    学生成绩管理系统 前言 一 我是一个菜鸟 二 已经有快一年没有发文章 一直在忙着毕业和找工作的事 如今生活逐渐趋于稳定 那么 勤劳的博主又开始更新了 哈哈 本次更新的是非常经典的学生成绩管理系统 这作为一个计算机专业的你来说 可能在大一 大
  • 让chatgpt从一个查询接口写接口测试用例

    要求 一个查询接口 入参有currPage order pageSize sortBy 所有入参为非必须 请帮我写出这个接口所有接口用例 根据你提供的信息 下面是该查询接口所有可能的接口用例 当所有参数都不传递时 查询接口会返回所有符合条件
  • UE44如何使用Geometry(BSP)笔刷,快速创建游戏原型?

    游戏原型搭建 如何快速搭建场景 一 好处1 防止同时也放大了对应的网格 如果像unity里面一样 R放大缩小以后 网格也会对应拉伸 失真 导致了材质会被拉伸或者缩小 1 选择Geometry 在BrushSetting里面 将X Y Z对应
  • ubuntu 20.04 安装 pycharm 2022.1 .3 及其卸载

    下载 官网下载 https www jetbrains com pycharm 安装 下载好的文件显示如下 打开终端 进入你刚下载的文件所在的文件夹目录 例如我的放在Downloads这个文件夹 cd Downloads 查看文件夹里的文件
  • ROS navigation分析:navigation框架

    前言 ROS navigation stack是ROS提供的一个非常重要且常用的模块 它的主要作用是实现机器人的定位 导航和避障功能 在ROS wiki上 Maintainer把它的功能归纳为 It takes in information
  • 从零实现DevOps(五):Jenkins+SSH远程部署SpringBoot项目

    上篇文章 我从安装Jenkins插件开始 给大家讲解了如何从Jenkis本地环境中 以启动jar包脚本的方式部署SpringBoot项目 但是呢 以咱们日常的开发来说 所有服务都部署在一台服务器上根本就不是一个合理的方案 更不可能在所有服务
  • 基于FPGA的一维卷积神经网络CNN的实现(五)数据量化(附代码)

    数据量化 环境 Pytorch Pycham Matlab 订阅后有问题 或者需要该节的文件直接加微信 Crazzy M 说明 上一节已经通过Matlab中基础的乘加运算进行了CNN网络的前向计算过程 该节利用Matlab将导出的CNN网络
  • Object365数据/论文说明

    总览 1 目标检测数据 365类 约600k训练图片 超过一千万的bboxes 迄今为止最大的目标检测数据集 全注释的 2 服务于更好的未来研究 局部敏感类型的任务 如目标检测 语义分割 3 在COCO测试下 Objects365上预训练的
  • IDEA插件系列(33):RestfulTool插件——Restful服务开发辅助工具集

    1 插件介绍 RestfulTool插件 一套 Restful 服务开发辅助工具集 提供了一个 Services tree 的显示窗口 双击 URL 直接跳转到对应的方法定义 一个简单的 http 请求工具 支持 Spring 体系 Spr
  • npm install安装依赖总结

    node下载地址 https nodejs org en download releases 可以看到node版本 npm版本 node module版本 1 npm的全局安装路径 查看默认值 npm get prefix 默认是C Use
  • 五、网络编程之网络 IO 模型的本质.md

    IO 网络模型的本质 前置概念 1 用户空间和内核空间 学习 Linux 或者 IO 网络模型时 经常可以看到两个词 User space 用户空间 和 Kernel space 内核空间 简单说 Kernel space 是 Linux
  • 实例创建流程_ABAQUS复合材料建模及基本分析流程

    案例1 创建开孔矩形复合材料常规壳层合板 层合板一端固定 另一端施加拉伸载荷 对模型进行分析 查看每层单方向的应力 对比云图和加载时的铺层额方向 理解铺层方向与lamina材料的概念 0 1建立几何模型 利用Abaqus中composite
  • javaSE基础 数据库操作3之数据库恢复

    java基础 数据库操作3之数据库恢复 流程 上一篇写了数据的备份 本篇将写数据库的恢复操作 思想 备份文件中写入的是将数据库表转换为sql后的语句 所以备份就只需将备份文件中的sql语句执行即可 数据库恢复 public static v
  • uni-app转小程序遇到的问题 (组件使用插槽的问题)(跨端兼容、条件编译)(小程序自定义胶囊按钮封装)(uni-app挂载原型链)

    1 uni app转小程序组件使用插槽的问题 uni app封装的组件使用问题 1 插槽样式 H5页面编译是有效果的 在小程序中编译的位置错误 它会跳出本来的插槽位置到最后 解决方法 使用父传子传递值 就可以继承组件的样式 封装的组件 使用
  • python使用from keras.utils import to_categorical出错

    python使用from keras utils import to categorical出错 我使用的python编辑环境Sublime Text keras的版本2 6 0 结果语句from keras utils import to
  • 【WiFi】国产WiFi芯片

    目录 1 概述 2 WiFi芯片的市场格局 3 中国的WiFi芯片公司 3 1 华为海思 3 2 乐鑫科技 3 3 博通集成 3 4 紫光展锐 3 5 康希通信 3 6 南方硅谷 4 国产WiFi芯片竞争格局 4 1 内卷WiFi 4 4
  • 芯片后端开发基础知识(二)

    目录 1 静态时序分析 Static Timing Analysis 2 波形的压摆 Slew 3 信号偏斜 Skew 4 时序路径 Clock Path 5 时序弧 Timing Arc 6 时钟域 Clock Domain 7 工作环境
  • 【IPC-UNIX网络编程】第4章管道和FIFO

    1 一个简单的客户 服务器例子 Client从标准输入 stdin 读进一个路径名 并把它写入IPC通道 Server从该IPC通道读出这个路径名 并尝试打开其文件 若server能打开该文件 它能读出其中的内容 并写入 不一定同一个 IP