【Linux】C语言缓冲区、缓冲区的实现

C语言中的缓冲区是什么意思? 缓冲区是指在计算机内存中分配的一块连续存储区域,用于临时存储数据。它的主要目的是减少I/O操作的频率,提高数据处理的效率。在C语言中,缓冲区通常以数组或指针的形式实现。缓冲区是C语言编程中的重要概念,它们用于临时存储数据,提高了I/O操作的效率和性能。本文详细介绍了缓冲区的定义、类型、实现原理和应用场景,并通过示例代码展示了缓冲区在实际编程中的应用。理解和正确使用缓冲区对于编写高效和健壮的C程序至关重要。希望通过本文的讲解,读者能对C语言中的缓冲区有一个全面深入的了解,并能在实际编程中灵活应用这些知识。 阅读详情

目录

一、C语言缓冲区

1.1 什么是缓冲区

1.2 缓冲区刷新

1.3 问题解释

1.4 stdout与stderr

1.5 perror的实现 

二、模拟实现缓冲区

2.1 接口展示

2.2 函数实现

2.3 测试与源代码


一、C语言缓冲区

1.1 什么是缓冲区

缓冲区本质是一块C语言提供的内存空间,这块内存区用来缓存待处理的数据。

缓冲区的刷新策略:

  1. 立即刷新。(IO次数多,效率低)
  2. 行刷新 (\n)。
  3. 满刷新(全缓冲),即写满缓冲区再刷新。(效率最高)

但是还有一些特殊的刷新策略:

  1. 用户强制刷新( fflush )
  2. 进程退出

对于不同文件有着不同的刷新策略

显示器对应的刷新策略为行缓冲 (为了兼顾用户体验)

而磁盘文件倾向为全缓冲的刷新策略。

其实所有的设备都倾向于全缓冲,因为全缓冲这种刷新策略可以减少IO的次数,也就是减少外设的访问次数,这种方式效率是最高的。

1.2 缓冲区刷新

关于为什么上篇文章中实现重定向功能,最后要使用fflush进行刷新缓冲区这个问题我们进行讲解,我们先来看看下面这段代码,分析了下面这段代码自然就理解了这个没有解决的问题 了。

但是,如果使用重定向操作,奇怪的现象就出现了。

C语言提供的打印函数都执行了两次,而系统调用(write)就输出了一次。

这必然和上面我们所说的缓冲区对显示器和磁盘文件的刷新策略不同导致的。

具体原因解释如下:

1.如果我们向显示器打印,则刷新策略则是行刷新,那么最后执行fork时——函数已经执行结束,内容已经被刷新至系统。(此时 fork 无意义)

2.如果将该程序进行重定向至文件进行打印,则让原本向显示器进行的行刷新变为了向磁盘文件的满刷新,此时\n无意义。

执行到fork时,函数执行结束,数据仍存在于对应进程的C标准库缓冲区中,没有被刷新至系统。

3.此时缓冲区的数据属于父进程的数据,fork创建子进程,子进程暂时使用父进程内的数据。

4.当执行至return 0时,父子进程准备相继退出时进行缓冲区内容的刷新,因为刷新数据属于一种写入操作,所以发生写时拷贝,父子进程相继将缓冲区中的数据刷新至系统,系统再输入至磁盘文件中。

其实很好证明我们上面的观点,我们只要在fork之前进行fflush,刷新缓冲区,就可以做到无论输出到文件还是显示器,结果都一样。

结果如下:

此时又引申一个问题,我们fflush函数中只是传入了stdout,就刷新了缓冲区?

原因如下:

在文件  /usr/include/libio.h 中,我们可以找到 FILE 结构体的定义

1.3 问题解释

再昨天讲述输出重定向的原理时,留下的一个问题就是什么一定要在关闭文件前进行进行缓冲区的刷新。

有了上面的讲解其实这个问题也就很好解释了。

因为我们关闭了 stdout 对应的文件描述符1,此时log.txt对应的文件描述符 fd 就是1。然后我们调用printf 向 stdout( fd==1 ) 的缓冲区中存放数据,如果不调用fflush刷新stdout的缓冲区,则该文件直接被close关闭,缓冲区中的数据也就丢失了。

1.4 stdout与stderr

首先我们来看一段代码

int main()
{
	int fd = open("log.txt", O_RDONLY);
	if (fd < 0)
	{
		myperror("open");
		return 1;
	}
	//stdout -> 1
	printf("hello printf 1\n");
	fprintf(stdout,"hello fprintf 1\n");
	// stderr -> 2

	perror("hello perror 2"); //stderr

	const char *s1 = "hello write 1\n";
	write(1, s1, strlen(s1));

	const char *s2 = "hello write 2\n";
	write(2, s2, strlen(s2));

	// cout -> 1
	std::cout << "hello cout 1" << std::endl;
	// cerr -> 2
	std::cerr << "hello cerr 2" << std::endl;
    return 0;
}

执行结果如下:

然后我们进行重定向(就会出现差别了):

进行重定向时,默认将fd为1处的指向进行了覆盖,在C语言中就是覆盖了stdout。

本质上,1和2对应的都是显示器文件,但是他们两个是不同的,可以认为stdout和stderr是同一个显示器文件被打开了两次。

这样的好处就在于,我们可以将stdout的内容存放至运行日志,将stderr的内容存放至错误日志,有利于程序的排错与测试。向下图这样:

 当然我们可以将stdout、stderr的内容都重定向到一个文本中。

这里的原理是,结合文件描述中dup2的理解,先将fd为1处的指向改为指向log.txt,然后取出1处的数据再放入到fd为2处,这样fd为1、fd为2处都指向了log.txt。本质其实还是重定向。

1.5 perror的实现 

perror 不同于printf,perror是向2号文件描述符写入,printf是向1号文件描述符写入。

perror 本质就是在读取程序中的 errno 的值,然后打印处对应的错误信息。

我们可以引入头文件<errno.h>来修改程序的错误码,让perror打印对应的错误信息,这就是perror的原理。

 接下来就模拟实现一下

我们要使用strerror函数,这个函数的功能就是输入程序的错误码从而打印对应的错误信息。

实现与结果如下:

二、模拟实现缓冲区

2.1 接口展示

为了加深我们对C标准库中缓冲区的理解,我们打算模拟实现一下缓冲区。

接下来是我们打算实现的接口以及测试的方式:

//缓冲区的大小
#define NUM 1024

typedef struct MyFILE {
	int fd;
	char buffer[NUM];
	int end;
}MyFILE;

MyFILE* _fopen(const char* pathname, const char* mode)
{}

	
void _fputs(const char* message, MyFILE* fp)
{}

void _fflush(MyFILE* fp)
{}

void _fclose(MyFILE* fp)
{}

int main()
{
	MyFILE* fp = _fopen("log.txt", "w");
	if (fp == NULL)
	{
		printf("open file error");
		return 0;
	}
	_fputs("hello world1\n", fp);
	_fputs("hello world2\n", fp);
	_fputs("hello world3\n", fp);
	_fflush(fp);
	_fclose(fp);
	return 0;
}

我们在主函数中的测试代码其功能为:

使用我们的_fopen函数以写的方式打开文件log.txt,用MyFILE指针接受其返回值,用fputs往fp指向的文件中输入信息,因为是往磁盘文件进行写入文件,所以我们使用_fflush刷新缓冲区,将内容输入至内核中,再由操作系统写入至log.txt中,最后使用_fclose关闭文件。

2.2 函数实现

1._fopen

判断参数正确性后,接着我们要判断用户是以什么方式打开文件(使用strcmp进行判断)。

然后调用open函数打开文件,传入对应的选项。如果文件打开成功,申请MyFILE结构体,返回该结构体的地址即可后序进行访问文件。

MyFILE* _fopen(const char* pathname, const char* mode)
{
	assert(pathname && mode);
	MyFILE* fp=NULL;
    //因为stdin的fd为0.
	int fd = -1;
	if (strcmp(mode, "r") == 0)
	{
		fd = open(pathname,O_RDONLY);
	}
	else if (strcmp(mode, "w") == 0)
	{
		//打开文件,传入3个选项:只读、创建、清空,设置权限为0666
		int fd = open(pathname, O_WRONLY | O_TRUNC | O_CREAT, 0666);
	}
	else if (strcmp(mode, "a") == 0)
	{
		fd = open(pathname, O_WRONLY | O_APPEND | O_CREAT, 0666);
	}
	if (fd >= 0)
	{
		//申请一个FILE结构体
		fp = (MyFILE*)calloc(1, sizeof(MyFILE));
		fp->fd = fd;
	}
	return fp;
}

2._fputs

判断参数正确性后,我们将数据拷贝到我们的缓冲区中,并调整对应 fp 中的数据个数(end)。

注意:向C语言默认打开的3个文件流(stdin、stdout、stderr)中进行打印时,要进行特殊的缓冲区刷新处理。比如向显示器中打印时刷新策略会变为行刷新,例如语句:_fputs(stdout,"hello\n");

void _fputs(const char* message, MyFILE* fp)
{
	assert(message && fp);
	//将字符串写入到缓冲区中
	strcpy(fp->buffer + fp->end, message); //adcde\0
	fp->end += strlen(message); 

	//如果是标准输入输出
	if (fp->fd == 0)   //暂不实现 
	{}
	else if (fp->fd == 1)
	{
		//输出到显示器 刷新策略改变为行刷新
		if (fp->buffer[fp->end - 1] == '\n')
		{
			write(fp->fd, fp->buffer, fp->end);
			fp->end = 0;
		}
	}
	else if (fp->fd == 2) {} //暂不实现 
	else {}  //暂不实现 
}

3._fflush

_fflush的其实就是将C语言中缓冲区的数据调用write接口传入系统内核的缓冲区中,所以当我们检测到如果C缓冲区不为空,则调用write进行刷新。

注意:此时调用write接口只是将数据传入系统中,这里我们还可以将内核中的数据直接刷新到磁盘中。调用的接口是syncfs,直接将fd传入即可。

void _fflush(MyFILE* fp)
{
	assert(fp);
	if (fp->end != 0)
	{
		//暂且将数据写入至内核
		write(fp->fd, fp->buffer, fp->end);
		//将数据从内核刷新至外设
		syncfs(fp->fd);     
		fp->end = 0;
	}
}

4._close

_close的实现就是调用close接口即可,只不过在调用之前要先进行缓冲区的刷新。

void _fclose(MyFILE* fp)
{
	//close之前,先进行刷新
	assert(fp);
	_fflush(fp);
	close(fp->fd);
	free(fp);
}

2.3 测试与源代码

测试代码如下:

执行结果: 

全部代码:

#include <stdio.h>                                                                     
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>

//缓冲区的大小
#define NUM 1024

typedef struct MyFILE {
	int fd;
	char buffer[NUM];
	int end;
}MyFILE;

MyFILE* _fopen(const char* pathname, const char* mode)
{
	assert(pathname && mode);
	MyFILE* fp=NULL;
	int fd = -1;
	if (strcmp(mode, "r") == 0)
	{
		fd = open(pathname,O_RDONLY);
	}
	else if (strcmp(mode, "w") == 0)
	{
		//打开文件,传入3个选项:只读、创建、清空,设置权限为0666
		int fd = open(pathname, O_WRONLY | O_TRUNC | O_CREAT, 0666);
	}
	else if (strcmp(mode, "a") == 0)
	{
		fd = open(pathname, O_WRONLY | O_APPEND | O_CREAT, 0666);
	}
	if (fd >= 0)
	{
		//申请一个FILE结构体
		fp = (MyFILE*)calloc(1, sizeof(MyFILE));
		fp->fd = fd;
	}
	return fp;
}
	
void _fputs(const char* message, MyFILE* fp)
{
	assert(message && fp);
	//将字符串写入到缓冲区中
	strcpy(fp->buffer + fp->end, message); //adcde\0
	fp->end += strlen(message); 

	//如果是标准输入输出
	if (fp->fd == 0)   //暂不实现 
	{}
	else if (fp->fd == 1)
	{
		//输出到显示器 刷新策略改变为行刷新
		if (fp->buffer[fp->end - 1] == '\n')
		{
			write(fp->fd, fp->buffer, fp->end);
			fp->end = 0;
		}
	}
	else if (fp->fd == 2) {} //暂不实现 
	else {}  //暂不实现 
}

void _fflush(MyFILE* fp)
{
	assert(fp);
	if (fp->end != 0)
	{
		//暂且将数据写入至内核
		write(fp->fd, fp->buffer, fp->end);
		//将数据从内核刷新至外设
		syncfs(fp->fd);     
		fp->end = 0;
	}
}

void _fclose(MyFILE* fp)
{
	//close之前,先进行刷新
	assert(fp);
	_fflush(fp);
	close(fp->fd);
	free(fp);
}

int main()
{
	MyFILE* fp = _fopen("log.txt", "w");
	if (fp == NULL)
	{
		printf("open file error");
		return 0;
	}
	_fputs("hello world1\n", fp);
	_fputs("hello world2\n", fp);
	_fputs("hello world3\n", fp);
    //直接往屏幕上输出(用于测试)
    
	_fflush(fp);
	_fclose(fp);
	return 0;
}

最后就是模拟向显示器打印,从而改变刷新策略从满刷新到行刷新的测试。

 结果如下:

 

Linux缓冲区续集——手撕fopen、fwrite、fflush、fclose等C库函数 Linux文件系统中,对于缓冲区的问题,继续深入理解C库函数fopen、fclose、fwrite、fflush等函数的底层实现,它们都以缓冲区为核心实现 阅读详情

相关推荐

Linux C语言实现轻量级消息队列:从环形缓冲区到多线程通信

消息队列是一种实现异步解耦的核心通信机制,其原理基于生产者-消费者模型,通过缓冲区暂存数据,实现不同组件间的松耦合通信。在Linux C编程中,利用互斥锁和条件变量可以构建线程安全的环形缓冲区,确保多线程环境下的数据同步与顺序执行。这种轻量级实现避免了Kafka、RabbitMQ等重型中间件的依赖,特别适用于嵌入式系统、高性能中间件等需要极致控制力和低开销的场景。通过固定消息长度和环形缓冲区设计,开发者能精准管理内存与锁竞争,为Web服务器请求缓冲、日志收集等应用提供可靠基础。本文以Linux C实现为例,

weixin_29175469的博客 276

查缺补漏C语言:缓冲区(缓存)

但是有了缓冲区,就可以将数据先放入缓冲区中(内存的读写速度也远高于硬盘),然后程序可以继续往下执行,等所有的数据都准备好了,再将缓冲区中的所有数据一次性地写入硬盘,这样程序就减少了等待的次数,变得流畅起来。有时候,从键盘输入的内容,或者将要输出到显示器上的内容,会暂时进入缓冲区,待时机成熟,再一股脑将缓冲区中的所有内容“倒出”,我们才能看到变量的值被刷新,或者屏幕产生变化。在实际开发中,将数据写入文件后,打开文件并不能立即看到内容,只有清空缓冲区,或者关闭文件,或者关闭程序后,才能在文件中看到内容。...

有朋自远方来,不亦乐乎。 1万+

C语言FILE结构体以及缓冲区深入探讨(unix/linux编程实现2.4)

在C语言中,用一个指针变量指向一个文件,这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。 定义文件指针的一般形式为:     FILE  *fp; 这里的FILE,实际上是在stdio.h中定义的一个结构体,该结构体中含有文件名、文件状态和文件当前位置等信息。我们通过fopen返回一个文件指针(指向FILE结构体的指针)来进行文件操作。

leilixu的专栏 2007

C语言之清空缓存区

在C语言中,我们常常需要去清空缓存区,对于缓存区清空的重要性,接下来我们进行具体的说明。 首先我们先解释一下缓存区。1.缓存区C语言中的缓冲区又称为缓存,它是内存空间的一部分。   也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。     C语缓冲区分为三种类型:1、全缓冲 2、行缓冲 3、不带缓冲。   缓冲区根据其对应的是输

宇哲 9万+

【C语言拓展】缓冲区、结构体大小计算、命令行参数

本节课主要讲的是缓冲区和结构体大小的计算之谜(二)提示:以下是本篇文章正文内容,下面案例可供参考1、缓冲区有很多:输入缓冲区,输出缓冲区,文件缓冲区,键盘缓冲区,输出双缓冲等等。有时候还叫 buf,爸福。都是一个东西。2、缓冲区本质就是一段连续的空间,比如 char a[40];,a 就是一段连续的 40 字节的空间。3、这个名字是根据它的功能来的,用来处理输入数据的,就叫输入缓冲区,用来处理输出 数据的就叫输出缓冲区,宏观上取个名字,方便程序猿分析使用。4、缓冲具体是什么样的意义?...

m0_62599305的博客 1652

工程师职级胜任力框架

一、前言 尽管这些年国内的IT行业发展迅速,但是仍然欠缺一套比较综合性的面向工程师的职级胜任力框架,造成国内很多工程师大都一心只想成为技术大牛,而忽视了自己全方位的工程师职业素养和能力的培养。 最近我有幸读到了Circle CI公司分享的工程胜任力矩阵,发现这份文档就是一份比较贴合互联网研发型企业的工程师职级胜任力框架,于是我在它的基础上,重新整理出了一份更适合国内工程师阅读的《工程师职级胜任力框架》,并把它分享在波波的github站点上,希望这份文档对工程师的职业开发和成长有帮助。注,Circle CI.

架构师波波的专栏 6334

深入理解Linux系统内存中文件结构以及缓冲区,模拟实现c语言库文件接口

本文系统介绍了Linux文件操作的核心概念与技术要点。主要内容包括:1)文件描述符的本质是数组下标,通过进程PCB中的files_struct结构体访问文件;2)重定向通过dup2系统调用实现文件描述符表项的覆盖;3)缓冲区分为语言层和系统层,采用不同的刷新策略(行刷新/全刷新);4)模拟实现了C标准库的FILE结构,包含文件描述符、缓冲区和刷新策略。文章通过代码示例详细演示了文件操作接口的使用方法,并深入分析了缓冲区的刷新机制和工作原理。

2302_80105876的博客 2287

Dobot Magician机械臂二次开发指南:如何利用Python脚本和I/O接口实现自动化任务

本文详细介绍了Dobot Magician机械臂的二次开发方法,重点讲解如何通过Python脚本和I/O接口实现高级自动化任务。内容包括开发环境搭建、运动控制API解析、I/O接口应用以及典型场景实现,帮助开发者充分发挥Dobot Magician的潜力,适用于工业自动化、教育科研等领域。

weixin_26968079的博客 267

linux下C语言实现多线程通信—环形缓冲区,可用于生产者(producer)/消费者(consumer)

一、概念引入 日常生活中,每当我们缺少某些生活用品时,我们都会去超市进行购买,那么,你有没有想过,你是以什么身份去的超市呢?相信大部分人都会说自己是消费者,确实如此,那么既然我们是消费者,又是谁替我们生产各种各样的商品呢?当然是超市的各大供货商,自然而然地也就成了我们的生产者。如此一来,生产者有了,消费者也有了,那么将二者联系起来的超市又该作何理解呢?诚然,它本身是作为一座交易场所而诞生。 将上述场景例比到我们实际的软件开发过程中,经常会见到这样一幕:代码的某个模块负责生产数据(供货商),而生产出来的数据却

qinjie的博客 1745

Xiaojie雷达之路---毫米波雷达基础知识---中频信号的相位

本篇文章主要介绍毫米波雷达的基础知识中的中频信号的相位 文章目录傅里叶变换的快速回顾中频信号的相位中频信号对物体微小位移的灵敏度如何2个chirps来对一个物体的速度进行测量测量一个振动的物体 傅里叶变换的快速回顾 傅里叶变换是将一个信号从时域中转换到频域中,在时域中的一个正弦信号将在频域中产生一个峰值,在大多数情况下,在频域中的一个信号是一个复数(每个值是一个振幅和相位的向量),表示为AejθAe^{j\theta}Aejθ 在频域中峰值的相位等于正弦函数的初始相位 中频信号的相位 上一篇文章中提到,

XiaoJie的博客 1万+

自定义串口通讯协议

自定义串口通讯协议的实现方法

qq_44826038的博客 2173

C语言中如何清空键盘缓冲区,Linux和Windows下完美实现

在linux下调试程序,遇到了用户输入问题,具体说就是getchar() scanf()问题,用了rewind(),fflush()方法都不好使,看了一篇文章后才知道linux下得用setbuf(),于是万事大吉也。故转之。   清空键盘缓冲区很多种方法,如用fflush(stdin); rewind(stdin);等,但是在linux这些都不起作用,还得我今天试了半天都没成

stormlovetao的专栏 2754

从 SEGW 到 SADL 的那根线,彻底理解 OData Data Source Mapping

本文摘要(150字): 在SAP Gateway的SADL型OData服务开发中,"Map to Data Source"是关键配置环节。与传统RFC映射不同,SADL映射不是针对单个CRUDQ操作,而是建立OData模型与SADL业务实体间的完整语义对应关系。通过属性映射和关联映射,系统能自动处理数据获取和导航请求。映射编辑器支持三种模式:属性映射处理字段对应,关联映射处理模型间关系,动作映射处理业务操作。映射的本质是建立语义翻译表,决定了后续OData请求如何转化为后端业务实体访问,而非简单的字段重命名

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 61

Linux | 缓冲区理解 | 模拟实现C语言文件操作函数

在Linux系统下,关于语言级别的缓冲区理解,并模拟实现相关函数,从而更深刻的理解缓冲区的概念

凡事都是靠练习 1134

C++笔记之emplace_back(),push_back()性能比较i++ 、 ++i

操作是否需要临时对象/拷贝性能需要(构造临时对象)较慢不需要(直接构造)较快i++需要(保存旧值)对于内置类型无影响,但对于自定义类型(如迭代器、大对象)会有拷贝开销++i不需要相对更快(尤其是自定义类型)都存在"是否需要额外的临时对象/拷贝"这一性能差异点和++i都是更高效的版本(避免临时对象/拷贝)和i++都可能产生额外的临时对象(前者构造临时对象,后者保存旧值)对于内置类型(如int),i++和++i性能几乎没有差异(编译器会优化);但对于自定义类型(尤其是迭代器等重量级对象),

小勇博客 101

Vue - 解决 Property or method “__v_isRef“ is not defined on the instance but referenced(浏览器控制台报错,代码没错)

vue,vue2控制台报错,vue报错Propertyormethod"__v_isRef"isnotdefinedontheinstancebutreferenced,vue代码没问题,但是报错Propertyormethod"__v_isRef"isnotdefinedontheinstancebutreferenced,vue2如何解决报错,vue怎么解决报错问题,vue2Propertyormethod"__v_isRef"isnotdefi

🏆 前端领域优质创作者 4503

C语言编程—清空键盘缓冲区,Linux下完美实现

/* *清空键盘缓冲区很多种方法,如用fflush(stdin);rewind(stdin);等,但是在linux这些都不起作用, *发现setbuf(stdin, NULL);就能直接清空键盘缓冲区了。 */ #include //清空缓冲区 int main() { char ch1; char ch2; scanf("%c", &ch1); print

cloud 的学习时代 1284

UE5 Niagara基础知识讲解

在UE5版本中,Niagara粒子系统引入了许多可添加的模块,分别用于控制发射器的生成和更新、粒子的生成和更新以及渲染效果。本文采用虚幻5.2.1版本,以图文方式对Niagara基础知识进行讲解。

一碗清深的博客 2472

Linux系统编程—I/O缓冲区(C语言实现)

定义:I/O缓冲区是指在内存里开辟的一块区域,用来存放接收用户输入和用于计算机输出的数据,以减小系统开销和提高外设效率。作用平滑I/O需求峰值:通过缓冲区,可以使得数据的传输更加平滑,避免因为I/O设备的速度差异而导致的数据传输瓶颈。提高系统速度:使用缓冲区可以使得用户进程在下一数据块读取的同时,处理已读入的数据块,从而提高系统的整体速度。

weixin_45706195的博客 1771

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Linux-缓冲区

本篇文章,继续来和大家分享与Linux相关的知识。本次内容主要涉及什么是用户级缓冲区,C语言缓冲区的原理和模拟C语言中的缓冲区。现象我们来做几个实验:第一个:编译运行,程序运行能正常输出,也能正常向文件写入第二个:我们在刚刚代码的基础上加上fork清空log.txt文件中的内容,编译运行。程序能正常输出,也能正常写入文件,...

weixin_37055290的博客 47

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Linux学习:C语言缓冲区与文件接口简单模拟实现

/刷新模式宏定义1<<11<<21<<3//刷新模式宏定义 # define NONE_FLUSH(1 << 1) # define LINE_FLUSH(1 << 2) # define FULL_FLUSH(1 << 3) //FILE类型 # define SIZE 4096 typedef struct _myFILE {//输入缓冲区 char outbuffer [ SIZE ];//输出缓冲区 int cap;//容量 int pos;

qq_71806743的博客 358

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

[Linux C]自己写的串口缓冲区

闲来没事自己写了一个串口缓冲区玩,利用数组实现,运行在Linux环境底下,gcc编译和自测试通过。 #include #include /* 缓冲区大小 */ #define SERIAL_BUFFER_SIZE 250 /* 错误代码:取负值是为了与正常数值区别开来 */ #define CODE_SUCCESS -1 #define CODE_NO_OPERATE -2

kinyanderson的专栏 3325

【Linux从入门到精通】C语言模拟实现进度条小程序

在Linux下,我们安装软件时会经常看到进度条,来告知我们安装的进度。我们不妨自己模拟实现一个进度条,看看其中的细节。模拟实现进度条并不困难,但其中的细节我们又不可忽视。本篇文章会对模拟实现进度条进行详解。其中还涉及到了缓冲区和回车、换行的概念和细节解释,超级详细!

weixin_67596609的博客 1917

【Linux后端服务器开发】缓冲区

缓冲区概述、语言层面缓冲区、C语言模拟实现stdio库

phoenixFlyzzz的博客 3146
上一篇: 【Linux】文件描述符、文件操作、重定向的模拟实现
下一篇: 【Linux】文件系统与inode、软硬链接
Brant_zero2022
博客等级 码龄5年 582粉丝 108原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Brant_zero2022

素材免费分享不求打赏,只求关注

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值