精华内容
下载资源
问答
  • 生产者消费者多缓冲区实现

    千次阅读 2015-01-13 19:19:20
    #include ...//全局变量,缓冲区 HANDLE g_EventBufferEmpty,g_EventBufferFull; const int END_PRODUCE_NUMBER=10; //生产者线程 DWORD ProducerThread(PVOID pm) { for(int i=1;i<=END_PRODUCE_N
    #include<stdio.h>
    #include<Windows.h>
    #include<process.h>
    int gBuffer=0;//全局变量,缓冲区
    HANDLE g_EventBufferEmpty,g_EventBufferFull;
    const int END_PRODUCE_NUMBER=10;
    //生产者线程
    DWORD ProducerThread(PVOID pm)
    {
    	for(int i=1;i<=END_PRODUCE_NUMBER;i++)
    	{
    		::WaitForSingleObject(g_EventBufferEmpty,INFINITE);
    		gBuffer=i;
    		printf("生产者放入数据%d\n",gBuffer);
    		::SetEvent(g_EventBufferFull);
    	}
    	return 0;
    }
    //消费者线程
    DWORD ConsumerThread(PVOID pm)
    {
    	while(gBuffer!=END_PRODUCE_NUMBER)
    	{
    		//等待生产者线程写入数据
    		::WaitForSingleObject(g_EventBufferFull,INFINITE);
    		printf("消费者从缓冲区中取出数据%d\n",gBuffer);
    		SetEvent(g_EventBufferEmpty);
    	}
    	return 0;
    }
    int main()
    {
    	g_EventBufferEmpty=CreateEvent(NULL,false,TRUE,NULL);
    	g_EventBufferFull=CreateEvent(NULL,false,false,NULL);
    	HANDLE hThread[2]={NULL};
    	DWORD ProduceID;
    	DWORD ConsumerID;
    	hThread[0]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ProducerThread,NULL,0,&ProduceID);
    	hThread[1]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ConsumerThread,NULL,0,&ConsumerID);
    	::WaitForMultipleObjects(2,hThread,true,INFINITE);
    	CloseHandle(hThread[0]);
    	CloseHandle(hThread[1]);
    	CloseHandle(g_EventBufferEmpty);
    	CloseHandle(g_EventBufferFull);
    }
    

    PS:在但缓冲区的环境下,我们只需要两个互斥变量,一个用来通知消费者消费gEventBufferFull,一个用于通知生产者生产gEventBufferEmpty,这样我们就可以实现了,而在多缓冲区的环境下使用互斥变量则有写捉襟见肘,而是需要使用可以计数的信号量来进行缓冲区的作用代码如下:

    //如果有两个缓冲区多个生产者,多个消费者呢?
    #include<Windows.h>
    #include<iostream>
    #include<process.h>
    #include<vector>
    using namespace std;
    const int END_PRODUCE_NUMBER=8;
    const int BUFFER_SIZE=4;
    int g_i=0,g_j=0;
    int gBuffer[BUFFER_SIZE]={0};
    //设置信号量和关键段
    CRITICAL_SECTION g_cs;
    HANDLE g_SemphBufferEmpty=0,g_SemphBufferFull=0;
    int mm[4]={0};
    int a=0;
    
    //生产者线程
    DWORD Produce(PVOID pm)
    {
    	for(int i=1;i<=END_PRODUCE_NUMBER;i++)
    	{
    		::WaitForSingleObject(g_SemphBufferEmpty,INFINITE);
    		//互斥访问的代码段
    		::EnterCriticalSection(&g_cs);
    
    		if(mm[g_i]!=1)
    		{
    			gBuffer[g_i]=i;
    			cout<<"生产者线程放入第"<<g_i<<"个缓冲池中的数据:"<<gBuffer[g_i]<<endl;
    			mm[g_i]=1;
    		}
    		g_i=(1+g_i)%BUFFER_SIZE;		
    		::LeaveCriticalSection(&g_cs);
    		::ReleaseSemaphore(g_SemphBufferFull,1,NULL);
    	}
    
    	cout<<"生产者完成任务\n";
    	a=1;
    	return 0;
    }
    //消费者线程
    DWORD Consumer(LPVOID pm)
    {
    	//只要有我们就可以进行消费
    	while(TRUE)
    	{
    		::WaitForSingleObject(g_SemphBufferFull,INFINITE);
    		::EnterCriticalSection(&g_cs);
    		//取出第一个可用数据
    		for(int i=0;i<4;i++)
    		{
    			if(mm[i]==1)
    			{
    				cout<<"消费者线程取出第"<<i<<"个缓冲池中的数据:"<<gBuffer[i]<<endl;		
    				mm[i]=0;	
    				break;
    			}
    		}						
    		::LeaveCriticalSection(&g_cs);
    		::ReleaseSemaphore(g_SemphBufferEmpty,1,NULL);
    		::Sleep(100);
    		int hh=0;
    		for(int i=0;i<4;i++)
    		{
    			if(mm[i]==0)
    				hh++;
    		}
    		if(hh==4&&a==1)
    		{
    			break;
    		}
    	}
    	cout<<"消费者完成任务"<<endl;
    	return 0;
    }
    int main()
    {
    	//开始初始化代码段
    	::InitializeCriticalSection(&g_cs);
    	//初始化信号量
    	g_SemphBufferEmpty=::CreateSemaphoreA(NULL,4,4,NULL);
    	g_SemphBufferFull=::CreateSemaphoreA(NULL,0,4,NULL);	
    	HANDLE hThread[3];
    	DWORD ThreadId;
    	hThread[0]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Consumer,NULL,0,&ThreadId);
    	hThread[1]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Produce,NULL,0,&ThreadId);
    	hThread[2]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Produce,NULL,0,&ThreadId);
    	::WaitForMultipleObjects(3,hThread,true,INFINITE);
    	for(int i=0;i<3;i++)
    	{
    		CloseHandle(hThread[i]);
    	}
    	CloseHandle(g_SemphBufferFull);
    	CloseHandle(g_SemphBufferEmpty);
    	::DeleteCriticalSection(&g_cs);
    }

    思路:主要就是最大值是4的信号量,我们根据这个信号量进行缓冲区的设置除了4个缓冲区gBuffer[4]以外还有一个对着4个缓冲区标志的索引mm[4],如果第i个缓冲区已经被使用那么mm[i]就为1,如果消费者对第j个缓冲区进行了消费,那么mm[j]=0;

    每次生产者对缓冲区操作的时候需要检测mm相对应位置上的值是不是0,每次消费者对缓冲区读取的时候需要检测mm对应的值是不是1,这样我们就完成了生产者消费者的线程模型

    展开全文
  • 多缓冲区--生产者-消费者问题

    千次阅读 2014-04-01 10:56:01
    //m个生产者-n个消费者-k个缓冲区 Buffer B[k]; Semaphore empty = k; Semaphore full = 0; Semaphore mutex = 1; //生产者消费者互斥访问缓冲区 in = 0; out = 0; process producer()_i{ while (true){ ...
    //m个生产者-n个消费者-k个缓冲区
    Buffer B[k];
    Semaphore empty = k;
    Semaphore full = 0;
    Semaphore mutex = 1;  //生产者消费者互斥访问缓冲区
    
    in = 0;
    out = 0;
    
    process producer()_i{
    	while (true){
    		produce();
    		P(empty);
    		P(mutex);
    		append() to B[in];
    		in = (in + 1) % k;
    		V(mutex);
    		V(full);
    	}
    }
    
    process consumer()_j{
    	while (true){
    		P(full);
    		P(mutex);
    		take() from B[out];
    		out = (out + 1) % k;
    		V(mutex);
    		V(empty);
    		consume();
    	}
    }

    展开全文
  • 1、文件编辑模式 ...(1)argument list模式,就是在打开Vim编辑器...(2)buffer list模式,就是在进入Vim编辑器后,打开缓冲区进行编辑。 2、单一缓冲区打开个文件 :files 显示目前打开了哪

    转载请注明本篇博文来自“柳大CSDN博客”:http://blog.csdn.net/poechant


    1、多文件编辑模式

    1argument list模式,就是在打开Vim编辑器时,携带多个文件路径参数。

    2buffer list模式,就是在进入Vim编辑器后,打开多个缓冲区进行编辑。


    2、单一缓冲区打开多个文件

    :files 显示目前打开了哪些文件

    :n 切换到下一个缓冲区内容

    :N 切换到上一个缓冲区内容

    :2n 切换到下下个缓冲区内容

    :bn 下一个缓冲区内容(buffer next

    :bp 上一个缓冲区内容(buffer previous


    3、多个缓冲区打开多个文件

    :sp [filename] 打开一个新的缓冲区,如果有filename则内容为该文件,否则为当前文件


    Ctrl+w n 新建一个缓冲区

    Ctrl+w q 退出光标所在的缓冲区


    Ctrl+w j 光标移动到下一缓冲区

    Ctrl+w k 光标移动到上一缓冲区

    Ctrl+w l 光标移动到右一缓冲区

    Ctrl+w h 光标移动到左一缓冲区


    Ctrl+w v 左右切割窗口新建缓冲区

    Ctrl+w s 上下切割窗口新建缓冲区


    Ctrl+w o 使光标所在缓冲区最大化,其他缓冲区隐藏


    转载请注明本篇博文来自“柳大CSDN博客”:http://blog.csdn.net/poechant

    -

    展开全文
  • 缓冲区

    千次阅读 2013-06-12 09:47:44
    什么是缓冲区缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区缓冲区根据其对应的是输入设备还是输出...

    什么是缓冲区


    缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。


    为什么要引入缓冲区


    我们为什么要引入缓冲区呢?

    比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。

    又比如,我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情。现在您基本明白了吧,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。

    缓冲区的类型

    缓冲区 分为三种类型:全缓冲、行缓冲和不带缓冲。

    1、全缓冲

    在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。

    2、行缓冲

    在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。

    3、不带缓冲

    也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。
    缓冲区的刷新

    下列情况会引发缓冲区的刷新:

    1、缓冲区满时;

    2、执行flush语句;

    3、执行endl语句;

    4、关闭文件。

    可见,缓冲区满或关闭文件时都会刷新缓冲区,进行真正的I/O操作。另外,在C++中,我们可以使用flush函数来刷新缓冲区(执行I/O操作并清空缓冲区),如:cout << flush; //将显存的内容立即输出到显示器上进行显示

    endl控制符的作用是将光标移动到输出设备中下一行开头处,并且清空缓冲区。

    cout < < endl;

    相当于

    cout < < ”\n”< < flush;

    通过实例演示说明

    1、文件操作演示全缓冲

    创建一个控制台工程,输入如下代码:

    #include< fstream >
    using namespace std;
    
    int main()
    {
        //创建文件test.txt并打开
    	ofstream outfile("test.txt");
    
        //向test.txt文件中写入4096个字符’a’
    	for(int n=0;n< 4096;n++)
    	{
    		outfile <<  'a';
    	}
        //暂停,按任意键继续
    	system("PAUSE");
        
        //继续向test.txt文件中写入字符’b’,也就是说,第4097个字符是’b’
    	outfile < <  'b';
    
        //暂停,按任意键继续
    	system("PAUSE");
    
    	return 0;
    }

    上面这段代码很容易理解,已经在代码内部作了注释。

    编写这段小代码的目的是验证全缓冲的大小是4096个字节,并验证缓冲区满后会刷新缓冲区,执行真正的I/O操作。

    编译并执行,运行结果如下:



    此时打开工程所在文件夹下的test.txt文件,您会发现该文件是空的,这说明4096个字符“a”还在缓冲区,并没有真正执行I/O操作。敲一下回车键,窗口变为如下:



    此时再打开test.txt文件,您就会发下该文件中已经有了4096个字符“a”。这说明全缓冲区的大小是4K(4096),缓冲区满后执行了I/O操作,而字符“b”还在缓冲区。
    再次敲一下回车键,窗口变为如下:



    此时再打开test.txt文件,您就会发现字符“b”也在其中了。这一步验证了文件关闭时刷新了缓冲区。


    2、键盘操作演示行缓冲


    先介绍getchar()函数。

    函数原型:int getchar(void);

    说明:当程序调用getchar()函数时,程序就等着用户按键,用户输入的字符被存放在键盘缓冲区中,直到用户按回车为止(回车字符也放在缓冲区中)。当用户键入回车之后,getchar()函数才开始从键盘缓冲区中每次读入一个字符。也就是说,后续的getchar()函数调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完后,才重新等待用户按键。

    不知道您明白了没有,再通俗一点讲,当程序调用getchar()函数时,程序就等着用户按键,并等用户按下回车键返回。期间按下的字符存放在缓冲区,第一个字符作为函数返回值。继续调用getchar()函数,将不再等用户按键,而是返回您刚才输入的第2个字符;继续调用,返回第3个字符,直到缓冲区中的字符读完后,才等待用户按键。

    如果您还没有明白,只能怨我表达能力有限,您可以结合以下实例体会。

    创建一个控制台工程,输入如下代码:

    #include < iostream >
    using namespace std;
    
    int main()
    {
    
    	char c;
    
    //第一次调用getchar()函数
    //程序执行时,您可以输入一串字符并按下回车键,按下回车键后该函数才返回
    	c=getchar();
    
        //显示getchar()函数的返回值
    	cout < <  c < < endl;
    
        //暂停
    	system("PAUSE");
     
    //循环多次调用getchar()函数
    //将每次调用getchar()函数的返回值显示出来
    //直到遇到回车符才结束
    	while((c=getchar())!='\n')
    	{
    		printf("%c",c);
    	}
    
        //暂停
    	system("PAUSE");
    
    	return 0;
    }

    这段小代码也很简单,同样在代码内部都有注释。

    getchar()函数的执行就是采用了行缓冲。第一次调用getchar()函数,会让程序使用者(用户)输入一行字符并直至按下回车键 函数才返回。此时用户输入的字符和回车符都存放在行缓冲区。

    再次调用getchar()函数,会逐步输出行缓冲区的内容。

    好了,本人表达能力有限,还是编译运行程序,通过运行结果自己领会吧。

    编译运行程序,会提示您输入字符,您可以交替按下一些字符,如下:




    您一直按下去,您就会发现当您按到第4094个字符时,不允许您继续输入字符。这说明行缓冲区的大小也是4K。

    此时您按下回车键,返回第一个字符’a’,如下图:



    继续敲一下回车键,将缓冲区的其它的字符全部输出,如下图:



    3、标准错误输出不带缓冲

    如错误输出时使用:

    cerr<<”错误,请检查输入的参数!”;

    这条语句等效于:

    fprintf(stderr, ”错误,请检查输入的参数!”);


    展开全文
  • 缓冲区和双缓冲区

    千次阅读 2020-07-24 15:26:55
    缓冲区 在单缓冲情况下,每当用户进程发出一I/O请求时,OS便在主存中为之分配一缓冲区。在块设备输入时,假定从磁盘把一块数据输入到缓冲区的时间为T,OS将该缓冲区中的数据传送到用户区的时间为M,而CPU对这一块...
  • AAudio 音频流内部缓冲区 与 音频数据读写缓冲区 概念 II . AAudio 音频流内部缓冲区 缓冲区帧容量 BufferCapacityInFrames 与 缓冲区帧大小 BufferSizeInFrames 区分 III . AAudio 音频流内部缓冲区 缓冲区帧容量 ...
  • 图详解缓冲区溢出问题

    万次阅读 多人点赞 2020-11-18 23:43:21
    缓冲区溢出一个常见的后果是:黑客利用函数调用过程中程序的返回地址,将存放这块地址的指针精准指向计算机中存放攻击代码的位置,造成程序异常中止。为了防止发生严重的后果,计算机会采用栈随机化,利用金丝雀值...
  • tcp缓冲区

    千次阅读 2019-02-08 16:40:39
    每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区。 二、缓冲区的意义 write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送到目标机器。一旦将...
  • 从抽象的角度看,也就是说,一个用户进程在内存中有自己的一个进程缓冲区,系统底层也有自己的一个内核缓冲区,read系统调用,就是将进程缓冲区中的数据复制到内核缓冲区中,而write系统调用则是将内核缓冲区中的...
  • C语言环形缓冲区

    2017-03-10 20:29:31
    C语言实现环形缓冲区,可供线程读写操作
  • 磁盘缓冲区和内存缓冲区

    千次阅读 2015-03-24 11:16:49
     意是上面说的内存缓冲区,只是它是专门为读取或写入磁盘而设置的,因此可以简称为磁盘缓冲区,这个的例子是很下载软件比如迅雷种都有的磁盘缓存设置,即先将数据下载到内存中缓存起来,达到一定数量后再写到磁盘...
  • 缓冲区溢出

    千次阅读 2018-08-10 17:30:15
    缓冲区溢出 相关安全文章 概览 描述 风险影响 例子 相关攻击 相关漏洞 相关控制 缓冲区溢出 今天又有点时间,花了大概4个小时不到翻译了这个大概3500字的文章,感觉自己阅读速度真的有待提高。虽说边翻译...
  • 用户进程缓冲区和内核缓冲区

    千次阅读 2019-04-29 16:20:46
    但实际上有一部分人把用户进程缓冲区和系统空间的缓冲区的概念混淆了,包括这两种缓冲区的用法和所要解决的问题,还有其它类似的概念。本文就来区分一下不同的缓冲区概念(主要针对类unix平台)。 用户进程和操作...
  • 缓冲区管理

    千次阅读 2019-09-03 23:20:50
     引入缓冲区的原因有很,可归结为以下几点:  (1) 缓和CPU与I/O设备间速度不匹配的矛盾。  (2) 减少对CPU的中断频率,放宽对CPU中断响应时间的限制。  (3) 解决数据粒度不匹配的问题。  (4) 提高CPU和I/O设备...
  • 缓冲区溢出攻击

    千次阅读 2020-05-12 23:44:35
    简单介绍缓冲区溢出攻击原理; 关闭防护措施,进行缓冲器溢出攻击实验; 最后从不同层次简单提及缓冲区溢出的防御措施;
  • 那么就可以将非阻塞I/O方式下的数据传输比做数据传输的集装箱方式(在字节和低层数据传输之间,了一层缓冲区,因此,可以将缓冲区看做是装载字节的集装箱)。  如果将同步I/O方式下的数据传输比做数据...
  • 日志缓冲区

    千次阅读 2013-07-18 20:51:57
    日志缓冲区是小型的,用于短期存储将写入磁盘上的重做日志的变更向量的临时区域。 “变更向量”是应用于某些对象的修改,执行DML语句会生成应用于数据的变更向量。 有了重做日志,可以确保数据永不丢失。执行DML...
  • 环形缓冲区

    千次阅读 2017-02-19 18:33:54
    圆形缓冲区(circular buffer),也称作圆形队列(circular queue),循环缓冲区(cyclic buffer),环形缓冲区(ring buffer),是一种数据结构用于表示一个固定尺寸、头尾相连的缓冲区,适合缓存数据流。...
  • UDP写缓冲区(发送缓冲区)分析

    千次阅读 2020-06-09 10:04:49
    最近,碰到UDP是否有写缓冲区的疑问,对于应用,如下图linux手册中有设置UDP发送缓冲区相关属性,也明确提到了send buffer的概念: 那这是否意味着UDP是有发送缓冲区的吗?我们再看一下《UNIX Network Programming...
  • SerialPort缓冲区

    万次阅读 2012-10-25 10:20:13
    SerialPort缓冲区中有:接收缓冲区,发送缓冲区,输入缓冲区,输出缓冲区,传输缓冲区。 例如: 串口属性:BytesToRead(获取接收缓冲区中数据的字节数)--这里提到的是“接收缓冲区” 串口属性:ReadBufferSize...
  • 数据缓冲区高速缓冲

    千次阅读 2015-09-26 15:19:36
    数据缓冲区高速缓冲 缓冲头部 一个缓冲区有两部分组成:一个含有磁盘上数据的存储数组和一个标识该缓冲区的 缓冲头部。...但是同一时刻,一个磁盘块不能映射到缓冲区中。 设备号字段和块号字
  • 队列1-环形缓冲区

    千次阅读 2019-01-27 16:58:34
    本篇为队列的第一篇文章,介绍基于数组结构的一个环形缓冲区队列。我觉得没有必要再从数组来写起,毕竟对于数组本身来说,我觉得是没有太可说的,但是基于数组的数据结构就有的说了。 什么是环形缓冲区 环形缓冲...
  • 圆形缓冲区

    千次阅读 2014-05-07 17:16:51
    圆形缓冲区(circular buffer),也称作圆形队列(circular queue),循环缓冲区(cyclic buffer),环形缓冲区(ring buffer),是一种数据结构用于表示一个固定尺寸、头尾相连的缓冲区,适合缓存数据流。...
  • scanf的缓冲区问题

    千次阅读 多人点赞 2018-07-06 10:45:07
    sacnf函数缓冲区问题,提供了正确解决缓冲区残留问题的几种方法。
  • Java 缓冲区续:字节缓冲区

    千次阅读 2012-11-06 22:25:22
    1 字节缓冲区API   所有基本类型(除布尔)都有相应缓冲区,但字节缓冲区有自己的独特之处。字节是操作系统以及IO使用的基本类型。当在JVM和操作系统间传递数据时,将其他的数据类型拆分成他们的字节是十分必要的。...
  • 浅析缓冲区溢出

    千次阅读 2018-08-14 11:34:35
    最近一直在学习缓冲区溢出漏洞的攻击,但是关于这一块的内容还是需要很相关知识的基础,例如编程语言及反汇编工具使用。所以研究透彻还需要不少的时间,这里简单的做一个学习的总结,通过具体的实验案例对缓冲区...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 564,522
精华内容 225,808
关键字:

多缓冲区