2017-09-11 20:45:37 qq_21792169 阅读数 6919
  • 网络工程师信道数据传输速率与码元速率强化训练教程

    网络工程师考试考察知识点繁多,形式多样。如何有效把握每种考察形式,拿到相应分数?这是历年考生挠头的事情。本系列课程紧抓考生痛点,对网工考试中重点题型分门别类讲解,反复强化训练,助力考生查缺补漏,拿到相应分数。本次分课程重点讲解了信道数据传输速率与码元速率的计算方法。通过基本概念阐述->历年真题强化训练->独家解题技巧总结,三大步骤帮助考生掌握信道数据传输速率与码元速率的计算方法,拿到相应分数。

    2955 人正在学习 去看看 徐朋

硬盘分为机械硬盘HDD和固态硬盘SSD两种。现在固态硬盘已经是大势所趋咯。SSD用的接口是NVME。在NVME协议下面还有一层PCIe协议。HDD硬盘接口有SATA,SATA接口常用的工作模式有AHCI。SATA硬盘接口最大速率是600MBytes/s。接下来我通过C代码测试SSD的读写性能。


代码采用的是直接IO方式,这个测的速率不加直接IO的四倍。

test_ssd.c

#define _GNU_SOURCE
#include<stdio.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
//#include <unistd.h>   /* add r/w include is error */

void print_usage(char *file)
{
	printf("Usage:\n");
	printf("%s   <filename>  <cnt>  <ONCE_SIZE>  <r/w>\n", file);
}

int main(int argc, char **argv)
{
	time_t Time_Start,Time_End;

	double run_time = 0;

	char* realbuff = NULL;

	int fd,i,cnt,block_size,szie;
	int pagesize,error,flags;

	if( argc!=5)
	{
		print_usage(argv[0]);
		return(-1);
	}

	if('r' == argv[4][0])
		{
		printf("running read operations....\n");
		flags = 0;
	}
	else if('w' == argv[4][0]){
		printf("running write operations....\n");
		flags = 1;		
	}
	else{
		printf("r/w error\n");
		return -1;
	}
	
	fd  = open(argv[1], O_CREAT | O_RDWR| O_DIRECT);
	if(fd <0){
		printf("open is fail\n");
		return-1;
	}
	
	pagesize=getpagesize();
	cnt = strtoul (argv[2], NULL, 0);
	szie = strtoul (argv[3], NULL, 0);
	block_size = (1024*1024*szie);
	realbuff = malloc(block_size+pagesize);
	if(realbuff ==NULL){
		printf("malloc realbuff is fail\n");
		return -1;
	}
	char *alignedbuff = (char*)((((unsigned int ) realbuff+pagesize-1)/pagesize)*pagesize);
	memset(alignedbuff,argv[1][1],block_size);
	
	if(1 == flags){
	Time_Start = clock();
	for(i=0;i<cnt;i++){
		error = write(fd, alignedbuff, block_size);		
		if(error <=0)
			{
			perror("error:");
			printf("write is fail\n");
			free(realbuff);
			return -1;
		}
	}
	//printf("%d %s %s\n",__LINE__,__FUNCTION__,__FILE__);

	Time_End = clock();		
	run_time = (double)(Time_End-Time_Start)/CLOCKS_PER_SEC;
	printf( "write %d M cost times:%f s\n",(szie*cnt),run_time);
	}
	else{
		Time_Start = clock();
		for(i=0;i<cnt;i++){
			error = read(fd, alignedbuff, block_size);		
			if(error <=0)
				{
				perror("error:");
				printf("write is fail\n");
				free(realbuff);
				return -1;
			}
		}

		Time_End = clock();	
		run_time = (double)(Time_End-Time_Start)/CLOCKS_PER_SEC;
		printf( "read %d M cost times:%f s\n",(szie*cnt),run_time);
	}
	
	free(realbuff);
	close(fd);
	return 0;
}


代码中红色部分需要注意,不能添加这个头文件,不然会出现读写错误,可能是这个头文件下面的write和系统调用不一样。没有去追究原因。测试结果如下:



将clock()函数更改为如下:

#include <sys/time.h>
long  get_ms()
{
struct timeval t;
long tick;
gettimeofday(&t,0);
tick=(long)(t.tv_sec)*1000+(long)(t.tv_usec)/1000;
return tick;
}

                                                                                                     By Design :Linux_Google 

2008-11-16 02:45:00 iteye_4515 阅读数 485
  • 网络工程师信道数据传输速率与码元速率强化训练教程

    网络工程师考试考察知识点繁多,形式多样。如何有效把握每种考察形式,拿到相应分数?这是历年考生挠头的事情。本系列课程紧抓考生痛点,对网工考试中重点题型分门别类讲解,反复强化训练,助力考生查缺补漏,拿到相应分数。本次分课程重点讲解了信道数据传输速率与码元速率的计算方法。通过基本概念阐述->历年真题强化训练->独家解题技巧总结,三大步骤帮助考生掌握信道数据传输速率与码元速率的计算方法,拿到相应分数。

    2955 人正在学习 去看看 徐朋
笔记本刚装了linux,想知道硬盘驱动程序是否正确安装了,以及硬盘读写速度。使用hdparm命令:
sudo apt-get install hdparm

sudo hdparm -v -i /dev/sda
其中参数-i用于测试硬盘速度,-v输出硬盘参数,/dev/sda指定测试哪一个硬盘(一定要放在最后)。

实现上,还有很多参数可于输出更多的硬盘信息,如-I用于输出硬件规格信息。执行man hdparm查看更多对数使用方法。
2013-03-14 23:35:59 ruiqingzheng 阅读数 378
  • 网络工程师信道数据传输速率与码元速率强化训练教程

    网络工程师考试考察知识点繁多,形式多样。如何有效把握每种考察形式,拿到相应分数?这是历年考生挠头的事情。本系列课程紧抓考生痛点,对网工考试中重点题型分门别类讲解,反复强化训练,助力考生查缺补漏,拿到相应分数。本次分课程重点讲解了信道数据传输速率与码元速率的计算方法。通过基本概念阐述->历年真题强化训练->独家解题技巧总结,三大步骤帮助考生掌握信道数据传输速率与码元速率的计算方法,拿到相应分数。

    2955 人正在学习 去看看 徐朋
我们通过hdparm程序来设置IDE硬盘
使用DMA和32位传输可以大幅提升系统性能。使用命令如下:

1 指定第一个IDE硬盘的PCI总线指定为32位,
# /sbin/hdparm -c 1 /dev/hda
 使用 -c 0参数来禁用32位传输。

2 使用DMA传输方式
在没有使用DMA前 我们先看硬盘读取速率
shell > hdparm -t /dev/hda #察看
/dev/hda: Timing buffered disk reads: 14 MB in 3.45 seconds = 4.06 MB/sec 
shell > hdparm -d 1 /dev/hda
shell > hdparm -t /dev/hda
 /dev/hda: Timing buffered disk reads: 82 MB in 3.02 seconds = 27.15 MB/sec
shell > hdparm -k 1 /dev/hda  # 保存设置



3 查看硬盘参数

[root@localhost root]# hdparm -v /dev/hda
/dev/hda:
 multcount    = 16 (on)
 IO_support   =  1 (32-bit)
 unmaskirq    =  0 (off)
 using_dma    =  1 (on)
 keepsettings =  1 (on)
 readonly     =  0 (off)
 readahead    =  8 (on)
 geometry     = 4865/255/63, sectors = 78165360, start = 0

4 hdparm其他常用参数

-g 显示硬盘的磁轨,磁头,磁区等参数。   
-i 显示硬盘的硬件规格信息,这些信息是在开机时由硬盘本身所提供。   
-I 直接读取硬盘所提供的硬件规格信息。   
-p 设定硬盘的PIO模式。   
-Tt 评估硬盘的读取效率和硬盘快取的读取效率。   
-u <0或1> 在硬盘存取时,允许其他中断要求同时执行。 
-v 显示硬盘的相关设定。
  
阅读(636) | 评论(0) | 转发(0) |
0

上一篇:加固SSH

下一篇:trap的使用

给主人留下些什么吧!~~
评论热议
2018-09-04 13:48:23 weixin_40343504 阅读数 1013
  • 网络工程师信道数据传输速率与码元速率强化训练教程

    网络工程师考试考察知识点繁多,形式多样。如何有效把握每种考察形式,拿到相应分数?这是历年考生挠头的事情。本系列课程紧抓考生痛点,对网工考试中重点题型分门别类讲解,反复强化训练,助力考生查缺补漏,拿到相应分数。本次分课程重点讲解了信道数据传输速率与码元速率的计算方法。通过基本概念阐述->历年真题强化训练->独家解题技巧总结,三大步骤帮助考生掌握信道数据传输速率与码元速率的计算方法,拿到相应分数。

    2955 人正在学习 去看看 徐朋

1、 通过命令“lspci -vvv |grep “Non-Volatile””查询被测PCIE SSD NVMe卡是否被识别到
#lspci -vvv |grep “Non-Volatile”
这里写图片描述
2、通过lspci查询命令lspci -s 85:00.0 -vvvxxx |grep “Speed”(85:0.0为ID号),查询PCIE SSD NVMe卡的最大速率和link协商速率是否正确
#lspci -s 85:00.0 -vvvxxx |grep “Speed”
这里写图片描述
3、执行以下命令,通知操作系统对此设备下电。以下命令中的“slotecho0&gt;/sys/bus/pci/slots/slot”为设备实际在服务器中的槽位号。 echo 0 &gt; /sys/bus/pci/slots/slot/power
$slot是采用lspci –vvv –ns 85:00.0 |grep Phy 命令查出来的Physical Slot number;
4.在30s后,再将被测PCIe硬盘插回先前的槽位,查询被测NVME硬盘端口速率协商是否正常。重复步骤2。

PS:Linux PCIE相关知识总结
1.首先我们先來复习一下 PCI-E bus 的速度上限.
• PCI Express 1.1
使用两对低电压的差位讯号排线(low-voltage differential signaling pairs),分別各跑 2.5GBit/s 速度,x1 有两对(传送与接收) 2.5 G x 2 = 5Gbps 的频宽.不过在讨论频宽时还是以单方向来计算.下面的速度是以单对的速度而言.
x1 2.5Gbps (20% overhead – PCI-e 在每八个位元的资料串上用十位元來加以编码) 2Gbps (250 MB/sec)
x4 10Gbps 8Gbps (1 GB/sec)
x8 20Gbps 16Gbps (2GB/sec)
x16 40Gbps 32Gbps (4GB/sec)
• PCI Express 2.0
PCI-SIG 的 PCI Express 2.0规格,新版每条 Lane 的单向频宽 2.5Gbps 倍增到 5Gbps.
x1 5Gbps (20% overhead – PCI-e 并且在每八个位元的资料串上用十位元來加以编码) 4Gbps (500 MB/sec)
(5G*0.8)Mb/8=500MB
x4 20Gbps 16Gbps (2 GB/sec)
x8 40Gbps 32Gbps (4 GB/sec)
x16 80Gbps 64Gbps (8 GB/sec)
• PCI Express 3.0
PCI-SIG 的 PCI Express 3.0 规格,新版每条 Lane 的单向频宽增到 8Gbps.
但因為编码方式改变了,相对于 2.0 之前采用 8b/10b (每10个bit只有8个是有效资料)而 3.0 编码方式为 128/130,所以资料传输频宽以及原始传输率基本当都可以算成 8Gbps.
x1 8Gbps (1GB/sec)
x4 32Gbps (4 GB/sec)
x8 64Gbps (8 GB/sec)
x16 128Gbps (16 GB/sec)
2.在 PCI 的裝置使用三个编号用來当做识别值,分别为
a.汇流排(bus number), b.装置 (device number) c. 功能(function number).(例如刚刚的 85:00.0 就是 bus number = 85 ,device number = 00 function = 0 )
这3个编号会组成 16-bits 的識別碼.
a. 汇流排(bus number) 8bits 2^8 至多可链接 256 个汇流排(0 to ff).
b. 装置(device number) 5bits 2^5 至多可接 32 种裝置(0 to 1f).
c. 功能(function number) 3bits 2^3 至多每种裝置可有 8 项功能(0 to 7).
3.
LnkSta :
目前系统所提供的速度 PCI-Express 1.0 ( 2.5G ) ,如果是 PCI-Express 2.0 那速度是 5G
LnkCap :
裝置目前所采用的速度.
LnkSta 和 LnkCap 这两个速度有可能不一樣 ,系統所提供的是 PCI Express 是 2.0 但裝置还是使用 1.0 的.

2019-09-26 14:37:29 qq_38639426 阅读数 150
  • 网络工程师信道数据传输速率与码元速率强化训练教程

    网络工程师考试考察知识点繁多,形式多样。如何有效把握每种考察形式,拿到相应分数?这是历年考生挠头的事情。本系列课程紧抓考生痛点,对网工考试中重点题型分门别类讲解,反复强化训练,助力考生查缺补漏,拿到相应分数。本次分课程重点讲解了信道数据传输速率与码元速率的计算方法。通过基本概念阐述->历年真题强化训练->独家解题技巧总结,三大步骤帮助考生掌握信道数据传输速率与码元速率的计算方法,拿到相应分数。

    2955 人正在学习 去看看 徐朋

LINUX系统写速度问题解决过程

问题描述:

linux系统下写速度只有2GB/s左右,无法支持2.5G采样率连续采集,达不到预期的性能。而同样的代码在windows系统下,却可以支持2.5G采样率连续采集,因此这里需要解决Linux系统的写速度问题。

尝试一:

刚开始以为是API的问题,查看资料发现大部分说法是mmap写文件最快,实际测试下来发现效果一般,没有特别惊艳的表现。加上使用不太方便,否定了这个解决方案。

尝试二:

由于用测速软件测试时两个系统里硬盘的顺序读写速度都是7~8GB/s,所以一开始我在Windows系统下对硬盘做了实际的测试,没有用测速软件,而是纯用writefile函数在写,发现读写在6GB/s左右。而且打开FILE_FLAG_NOBUFFRING标志位后才有这样的速度,不开的话会慢。如图

 

可以看出写速度约为5GB/s,读速度约为6GB/s。

然而我换到Linux系统后,也不用测速软件,纯用write函数,发现它的写速度只有2GB/s,但是读速度却在7GB/s。这让我十分怀疑是否是写操作有什么设置没有打开。一番实验查找之后,我发现Windows的raid卡的写策略是启动了写缓存,如图

 

但是我在Linux系统中却没有找到这样的设置或查询。不过在查看内核打印有一句"Write cache disabled,read cache enabled",如图:

 

可以看出正好是说写缓存关闭而读缓存打开,跟目前测试出来的情况一致。我一度以为已经找到了问题所在,但是使用hdparm磁盘管理工具却没办法查询或设置raid卡的写缓存

 

而且这句话是否是描述raid卡的也存疑,在尝试了另外一些设置硬盘写缓存的方法无效后,我放弃了这个解决办法。后来我也确定这句话描述的是另外一个硬盘,而不是我们用的raid卡。

尝试三:

于是我又回到了测试速度的工具上。linux下我用测速软件测得磁盘流盘速度为7000M左右。但是我用另一个linux下很常用的dd命令来测速时却和上个软件相差如此之大,如图:

我想是否是dd命令有一些关于写速度的参数设置,于是仔细研究了dd命令的参数设置后发现:

这些参数其中direct和nonblock跟我们在windows上采用的“FILE_FLAG_NOBUFFING”,即不使用缓冲区直接操作磁盘的方式相似。于是我对这两个做了测试之后,发现在用dd命令时,加上direct参数,跳过系统缓存,直接写到硬盘,在大量数据连续存储时可以提高性能。查资料后发现direct 模式是把写入请求直接封装成 I/O 指令发到磁盘,非 direct 模式只是把数据写入到系统缓存就认为 I/O 成功,并由操作系统决定缓存中的数据什么时候被写入磁盘。

 

结论:

因此我们可以得出这样一个结论,在linux系统中,IO写入的基本过程

a. 定位用户数据

b. 将用户数据拷贝至内核中(page cache)

 

先解释一下page cache。page cache是文件在内存中的缓存,打开文件时,先要把文件加载进pache cache,写入时也是一样,先写入page cache,再由page cache刷入磁盘。一般来说,page cache中的数据也是文件的一部分,所以如果数据写入了page cache,就可以认为io操作已安全完成。

 

上述的过程是一个非常简化的版本,实际的一些api比如fwrite()的实现可能是这样的

---用户层---

a. 定位用户数据

b. 将用户数据拷贝至函数的缓存中(函数调用返回)

 

---vfs层(即虚拟文件系统)---

c. 将函数缓存拷贝至内核缓存(page cache) (显式或隐式调用fflush() )

d. 将page cache中的脏数据写入磁盘数据区(调用硬盘驱动)

e. 将inode cache中的脏数据写入磁盘inode区(调用硬盘驱动)

 

---存储控制器层---

到目前为止,写入基本完成,数据被存储控制器接管,由于存储控制器自带板载电容,因此可以认为数据已固化

f. 从板载cache(比如ssd raid 卡)中读取数据

g. 将数据写入磁盘介质

 

对于linux的write()函数来说,调用在c步就返回了。而对于fwrite()这种经过一次封装的函数来说,它在write之上增加了一层缓冲,也就是说调用fwrite会在b步返回,为了保证数据写入文件,使用fwrite时,可以调用fflush()函数来保证调用到第c步。如果认为此时存储于操作系统的page cache仍不安全,可以继续调用fsync()来保证调用到第e步。(如果到了这里仍然觉得数据不够安全,可以将存储控制器的模式更改为write through,这样可以保证第g步完成后才返回)。

如果打开文件时采用了direct io的方式,可以绕开对于page cache的操作,就是绕过了d步,但是,e步并没有被绕过,因此,使用direct io方式时,为了保证数据的绝对安全,依旧需要调用fsync()来保证文件的元数据(inode等信息)写入磁盘(可以在open时增加O_SYNC,但这样会严重影响效率)。

 

因此对于写文件时要不要缓冲区这个事情,要从具体的应用角度去看。在需要频繁读取写入数据,并且数据的量不是很大时,通过缓存机制可以有效的提升读写数据的速度,因为当你要读取数据时,系统会先查看你要的数据是否在缓存里,如果在缓存中则直接提取,由于数据还没有真正的刷入硬盘中,因此这个操作是电子层面而非IO层面,速度要快的多。当缓存中的数据多到一定程度,系统才会将不常用的数据真正的写入磁盘。

而这种应用情景,大量数据需要快速的写入硬盘中,全部写完后,用户才有可能会继续回放文件等之类的操作,因此绕开缓存机制,直接以合适的block size循环的写入硬盘,则比用缓存的机制,让系统决定什么时候写入磁盘要快很多。

 

最后,direct方式是以扇区为单位操作磁盘,因此执行一次写入操作的最小单位是512 Bytes。而且direct方式不常用,在使用时要加一下宏定义_GNU_SOURCE或其他的,否则找不到“O_DIRECT”这个参数,它操作的内存也不能使用平常的定义数组的方式,应该要用mmap或malloc去申请内存,具体使用详情自行百度关键字。

最终的测试结果如图;

 

以下为测试源码:
 

#define _GNU_SOURCE 1

#define __USE_GNU 1



#include <stdio.h>

#include <assert.h>

#include <fcntl.h>

#include <getopt.h>

#include <stdint.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <time.h>



#include <sys/mman.h>

#include <sys/stat.h>

#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>



static void *mmap_control(int fd,long mapsize)

{

    void *vir_addr;

    vir_addr = mmap(NULL, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    return vir_addr;

}



void* pvAllocMemPageAligned (uint64_t qwBytes)

    {

    void* pvTmp;

    int fd = open ("/dev/zero", O_RDONLY);

    pvTmp = (void*) mmap (NULL, qwBytes, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);



    // set everything to zero to get memory allocated in physical mem

    if (pvTmp != MAP_FAILED)

       memset (pvTmp, 0, qwBytes);

    else

        pvTmp = NULL;



    close (fd);

    return (pvTmp);

    }



// ***********************************************************************



void vFreeMemPageAligned (void* pvAdr, uint64_t qwBytes)

    {

    munmap (pvAdr, qwBytes);

    }



static void timespec_sub(struct timespec *t1, const struct timespec *t2);



int main()

{

printf("CLOCKPERSEC=%ld\n",CLOCKS_PER_SEC);

char filename[64] = "/home/sample/SampleData/testspeed_rcv.bin";

int file_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC|O_DIRECT, 0666);

if(file_fd<0)

{

perror("rcv file err:");

}



int rc;

int size=2*1024*1024;

//char buffer[4*1024*1024]={0};

void *buffer=NULL;

buffer=pvAllocMemPageAligned(4*1024*1024);

/*void* control_base;

control_base=mmap_control(file_fd,size);

if(control_base=NULL||control_base==(void*) -1)

{

printf("映射失败\n");

close(file_fd);

return -1;

}*/

struct timespec ts_start, ts_end;

clock_gettime(CLOCK_MONOTONIC, &ts_start);

clock_t start1,end1;

     start1=clock();

printf("flag1\n");

int times=1000;

for(int i=0;i<times;i++)

{

//memcpy(control_base,buffer,size);

rc= write(file_fd, buffer, size);

if(rc!=size){

perror("write error:");

return -1;

}

}

end1=clock();

printf("flag2\n");

clock_gettime(CLOCK_MONOTONIC, &ts_end);

     float dur1=(float)(end1-start1);

printf("Cost Time=%f\n",(dur1/CLOCKS_PER_SEC));

printf("rc=%d\n",rc);

timespec_sub(&ts_end, &ts_start);

printf("Cost %ld.%09ld seconds (total) for transfer \n",

     ts_end.tv_sec, ts_end.tv_nsec);

printf("Write Speed=%f\n",(float)(size/1024/1024*times)/(ts_end.tv_sec+ts_end.tv_nsec/1e9));

 /*if(munmap(control_base,size)==-1)

    {

printf("munmap error!\n");

    }*/

close(file_fd);



file_fd=open(filename,O_RDWR|O_DIRECT);

if(file_fd<0)

{

perror("rcv file err:");

}

start1=clock();

clock_gettime(CLOCK_MONOTONIC, &ts_start);



for(int i=0;i<times;i++)

{

//memcpy(control_base,buffer,size);

rc= read(file_fd, buffer, size);

if(rc!=size)

{

printf("rc=%d\n",rc);

}

}



clock_gettime(CLOCK_MONOTONIC, &ts_end);

end1=clock();

dur1=(float)(end1-start1);

printf("\n\nCost Time=%f\n",(dur1/CLOCKS_PER_SEC));

printf("rc=%d\n",rc);

timespec_sub(&ts_end, &ts_start);

printf("Cost %ld.%09ld seconds (total) for transfer \n",

     ts_end.tv_sec, ts_end.tv_nsec);

printf("Read Speed=%f\n",(float)(size/1024/1024*times)/(ts_end.tv_sec+ts_end.tv_nsec/1e9));

close(file_fd);

vFreeMemPageAligned(buffer,4*1024*1024);

}

static void timespec_sub(struct timespec *t1, const struct timespec *t2)

{

  assert(t1->tv_nsec >= 0);

  assert(t1->tv_nsec < 1000000000);

  assert(t2->tv_nsec >= 0);

  assert(t2->tv_nsec < 1000000000);

  t1->tv_sec -= t2->tv_sec;

  t1->tv_nsec -= t2->tv_nsec;

  if (t1->tv_nsec >= 1000000000)

  {

    t1->tv_sec++;

    t1->tv_nsec -= 1000000000;

  }

  else if (t1->tv_nsec < 0)

  {

    t1->tv_sec--;

    t1->tv_nsec += 1000000000;

  }

}


 

LINUX IO 总结

阅读数 2322

没有更多推荐了,返回首页