日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用SG_IO发送SCSI 指令测试底层驱动的scatter-gather 功能

發布時間:2024/9/5 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用SG_IO发送SCSI 指令测试底层驱动的scatter-gather 功能 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://gmd20.blog.163.com/blog/static/16843923201002274341552/


Linux中的sg驅動 (“The Linux SCSI Generic (sg) Driver“ http://sg.danny.cz/sg/index.html) 是一個通用SCSI設備的模型,應用程序通過定義的“SG_IO ioctl ”可以像scsi磁盤等設備發送自定義的scsi指令集。? 2.6版本的,這個ioctl 將在? block驅動層的 (http://lxr.linux.no/#linux+v2.6.32/block/scsi_ioctl.c 文件的?
static int?sg_io(struct?request_queue?*q, struct?gendisk?*bd_disk, struct?sg_io_hdr?*hdr,?fmode_t?mode)

函數中得到處理,然后組成 request發送的底層的 scsi驅動。
使用的關鍵數據結構在? /include/scsi/sg.h 里面定義?
83typedef struct sg_io_hdr84{85 int interface_id; /* [i] 'S' for SCSI generic (required) */86 int dxfer_direction; /* [i] data transfer direction */87 unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */88 unsigned char mx_sb_len; /* [i] max length to write to sbp */89 unsigned short iovec_count; /* [i] 0 implies no scatter gather */90 unsigned int dxfer_len; /* [i] byte count of data transfer */91 void __user *dxferp; /* [i], [*io] points to data transfer memory92 or scatter gather list */93 unsigned char __user *cmdp; /* [i], [*i] points to command to perform */94 void __user *sbp; /* [i], [*o] points to sense_buffer memory */95 unsigned int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */96 unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */97 int pack_id; /* [i->o] unused internally (normally) */98 void __user * usr_ptr; /* [i->o] unused internally */99 unsigned char status; /* [o] scsi status */100 unsigned char masked_status;/* [o] shifted, masked scsi status */101 unsigned char msg_status; /* [o] messaging level data (optional) */102 unsigned char sb_len_wr; /* [o] byte count actually written to sbp */103 unsigned short host_status; /* [o] errors from host adapter */104 unsigned short driver_status;/* [o] errors from software driver */105 int resid; /* [o] dxfer_len - actual_transferred */106 unsigned int duration; /* [o] time taken by cmd (unit: millisec) */107 unsigned int info; /* [o] auxiliary information */108} sg_io_hdr_t; /* 64 bytes long (on i386) */


關于具體用法,可以在“The Linux SCSI Generic (sg) HOWTO http://tldp.org/HOWTO/SCSI-Generic-HOWTO/index.html” 找到一些說明,“sg3_utils(http://sg.danny.cz/sg/sg3_utils.html)”的源碼包里面的代碼很不錯的參考例 子,提供了各種scsi指令的封裝代碼,簡單的scsi指令測試也可以直接誒使用sg3_utils里面的命令就可以了。? 更多信息可以參考http://sg.danny.cz/sg/index.html 站點。


scatter-gather DMA
是一些磁盤或者網絡硬件的擴展特性,可以讓硬件設備在一次DMA映射里面訪問不連續的多塊內存,利用這個特性,可以直接讓用戶空間的地址直接映射DMA上 面去,減少傳輸過程中的數據復制量,提高系統西能。 “ Understanding the linux kernel ”一書的“block device” 一章的開頭部分有介紹。



如果構建多段的 scatter-gather?scsi request,可以參考sg3_utils 中的example目錄下的sg_iovec_tst 那個例子。我簡單修改一下源代碼,發送一個自定義的scatter-gather列表的read10 來讀磁盤的scsi request到設備的代碼。其中 單個request的扇區總數和 scatter-gather列表個數的限制和block驅動層數和scsi3層驅動的scsi_host等參數設置有關,scatter-gather 列表還可能依賴于硬件實現。?


#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "sg_lib.h"
#include "sg_io_linux.h"

/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
device driver.
*? Copyright (C) 2003-2007 D. Gilbert
*? This program is free software; you can redistribute it and/or modify
*? it under the terms of the GNU General Public License as published by
*? the Free Software Foundation; either version 2, or (at your option)
*? any later version.

This program will read a certain number of blocks of a given block size
from a given sg device node and write what is retrieved out to a
normal file. The purpose is to test the sg_iovec mechanism within the
sg_io_hdr structure.

Version 0.12 (20070121)
*/


#define ME "sg_iovec_tst: "

#define A_PRIME 509
#define IOVEC_ELEMS 2048

#define SENSE_BUFF_LEN 32
#define DEF_TIMEOUT 40000?????? /* 40,000 milliseconds */

struct sg_iovec iovec[IOVEC_ELEMS];

/* Returns 0 if everything ok */
int sg_read(int sg_fd, unsigned char * buff, int num_blocks, int from_block,
int bs)
{
unsigned char rdCmd[10] = {READ_10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char senseBuff[SENSE_BUFF_LEN];
struct sg_io_hdr io_hdr;
int dxfer_len = bs * num_blocks;
int k=0, pos =0, rem=0;

rdCmd[2] = (unsigned char)((from_block >> 24) & 0xff);
rdCmd[3] = (unsigned char)((from_block >> 16) & 0xff);
rdCmd[4] = (unsigned char)((from_block >> 8) & 0xff);
rdCmd[5] = (unsigned char)(from_block & 0xff);
rdCmd[7] = (unsigned char)((num_blocks >> 8) & 0xff);
rdCmd[8] = (unsigned char)(num_blocks & 0xff);

/*
for (k = 0, pos = 0, rem = dxfer_len; k < IOVEC_ELEMS; ++k) {
iovec[k].iov_base = buff + pos;
iovec[k].iov_len = (rem > A_PRIME) ? A_PRIME : rem;
if (rem <= A_PRIME)
break;
pos += A_PRIME;
rem -= A_PRIME;
}

*/
//create 32 x 509 scatter-gather list , so remain ">128kb data"? was split into the second request.

for (k = 0; k < 32; ++k) {
iovec[k].iov_base = buff + pos;
iovec[k].iov_len = 509;
pos += 512;
}

//put the remain into 2 scatter-gather list , so we don't exceed maxnium 64 segments.
rem = dxfer_len - (k+1) * 509 ;

iovec[k++].iov_base = buff + pos;
iovec[k++].iov_len = (rem /2) -3;

pos += rem /2 ;
iovec[k++].iov_base = buff + pos;
iovec[k++].iov_len = rem - (rem /2) + 3;


if (k >= IOVEC_ELEMS) {
fprintf(stderr, "Can't fit dxfer_len=%d bytes in iovec\n", dxfer_len);
return -1;
}
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = sizeof(rdCmd);
io_hdr.cmdp = rdCmd;
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.dxfer_len = dxfer_len;
io_hdr.iovec_count = k + 1;
io_hdr.dxferp = iovec;
io_hdr.mx_sb_len = SENSE_BUFF_LEN;
io_hdr.sbp = senseBuff;
io_hdr.timeout = DEF_TIMEOUT;
io_hdr.pack_id = from_block;

if (ioctl(sg_fd, SG_IO, &io_hdr)) {
perror("reading (SG_IO) on sg device, error");
return -1;
}
switch (sg_err_category3(&io_hdr)) {
case SG_LIB_CAT_CLEAN:
break;
case SG_LIB_CAT_RECOVERED:
fprintf(stderr, "Recovered error while reading block=%d, num=%d\n",
from_block, num_blocks);
break;
case SG_LIB_CAT_UNIT_ATTENTION:
fprintf(stderr, "Unit attention\n");
return -1;
default:
sg_chk_n_print3("reading", &io_hdr, 1);
return -1;
}
return 0;
}


int main(int argc, char * argv[])
{
int sg_fd, fd, res, j, m, dxfer_len;
unsigned int k, num;
int do_help = 0;
int blk_size = 512;
int count = 0;
char * sg_file_name = 0;
char * out_file_name = 0;
unsigned char * buffp;

for (j = 1; j < argc; ++j) {
if (0 == strncmp("-b=", argv[j], 3)) {
m = 3;
num = sscanf(argv[j] + m, "%d", &blk_size);
if ((1 != num) || (blk_size <= 0)) {
printf("Couldn't decode number after '-b' switch\n");
sg_file_name = 0;
break;
}
}
else if (0 == strncmp("-c=", argv[j], 3)) {
m = 3;
num = sscanf(argv[j] + m, "%d", &count);
if (1 != num) {
printf("Couldn't decode number after '-c' switch\n");
sg_file_name = 0;
break;
}
}
else if (0 == strcmp("-h", argv[j]))
do_help = 1;
else if (*argv[j] == '-') {
printf("Unrecognized switch: %s\n", argv[j]);
sg_file_name = 0;
break;
}
else if (NULL == sg_file_name)
sg_file_name = argv[j];
else
out_file_name = argv[j];
}
if ((NULL == sg_file_name) || (NULL == out_file_name) || (0 == count)) {
printf("Usage: sg_iovec_tst [-h] [-b=num] -c=num <generic_device> "
"<output_filename>\n");
printf("? where: -h?????? this usage message\n");
printf("???????? -b=num?? block size (default 512 Bytes)\n");
printf("???????? -c=num?? count of blocks to transfer\n");
printf(" reads from <generic_device> and sends to <output_filename>\n");
return 1;
}

sg_fd = open(sg_file_name, O_RDONLY);
if (sg_fd < 0) {
perror(ME "sg device node open error");
return 1;
}
/* Don't worry, being very careful not to write to a none-sg file ... */
res = ioctl(sg_fd, SG_GET_VERSION_NUM, &k);
if ((res < 0) || (k < 30000)) {
printf(ME "not a sg device, or driver prior to 3.x\n");
return 1;
}
fd = open(out_file_name, O_WRONLY | O_CREAT, 0666);
if (fd < 0) {
perror(ME "output file open error");
return 1;
}



count = 512 -1 ;? //don't exceed 256kb IO
blk_size = 512;???

dxfer_len = count * blk_size;? //最終生成的request的大小

const int inter_space= 1024;?

buffp = (unsigned char *)malloc(dxfer_len + inter_space);
if (buffp) {
if (0 == sg_read(sg_fd, buffp, count, 0, blk_size)) {
if (write(fd, buffp, dxfer_len) < 0)
perror(ME "output write failed");
}
free(buffp);
}
res = close(fd);
if (res < 0) {
perror(ME "output file close error");
close(sg_fd);
return 1;
}
res = close(sg_fd);
if (res < 0) {
perror(ME "sg device close error");
return 1;
}
return 0;
}

總結

以上是生活随笔為你收集整理的使用SG_IO发送SCSI 指令测试底层驱动的scatter-gather 功能的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 一本加勒比hezyo黑人 | 亚洲插插插 | 中国免费观看的视频 | 色导航在线 | 91视频大全 | 欧美日韩综合在线观看 | 亚洲精品久久久久久久蜜桃臀 | 欧美一区二区在线看 | 99热久久这里只有精品 | 肥老熟妇伦子伦456视频 | 欧美一级片在线 | 中文字幕123 | 国产aaa视频 | 淫语视频| 开心激情综合 | 朝鲜一级黄色片 | 国产精品久久综合视频 | 亚洲国产第一区 | 欧美99久久精品乱码影视 | 丝袜ol美脚秘书在线播放 | 色九月婷婷 | 国内av免费 | 久久美 | 精品无码一区二区三区 | 国产精品久久久久久久久久东京 | 国产精品久久久久电影 | 欧洲亚洲精品 | 欧美人与禽zoz0性3d | 女同hd系列中文字幕 | 99久视频 | www.操com | 77777av| 日韩中文字幕av | 88久久精品无码一区二区毛片 | 亚洲欧美综合 | 天天干天天爽 | 天天操夜夜爱 | 中文字幕无人区二 | 91av精品 | 超碰97国产精品人人cao | 不卡av影院 | 一区二区三区天堂 | www.日本精品 | 欧美激情aaa| 97国产在线播放 | 精品无码一区二区三区电影桃花 | 免费看黄色片视频 | 狠狠干夜夜骑 | 国产色站| 自由 日本语 热 亚洲人 | 激情综合一区二区三区 | 欧美精品一区二区不卡 | 97视频一区二区 | 尤果网福利视频在线观看 | 一级少妇女片 | 女生脱裤子让男生捅 | 无码人妻丰满熟妇区毛片18 | 真性中出 | 欧美区在线| 国产乡下妇女做爰毛片 | 欧美区在线观看 | 久久久www成人免费毛片 | 高潮无码精品色欲av午夜福利 | 91福利视频网 | 真性中出 | 中文字幕 欧美 日韩 | 草逼视频免费看 | 久久91亚洲精品中文字幕奶水 | 色爽 | 中文字幕在线视频观看 | 美腿丝袜亚洲综合 | 欧美大片网站 | 亚洲尤物在线 | 日韩成人黄色片 | 五月天综合视频 | 香港三日本三级少妇66 | 丁香啪啪 | 免费看日产一区二区三区 | www.色婷婷 | 日本不卡一区 | 日本一级黄色录像 | 一区中文字幕 | 十大黄台在线观看 | 三级成人 | 欧美激情专区 | 五月激情站 | av天堂一区二区三区 | 日韩www在线观看 | 国产91对白在线播放 | 日韩另类| 都市激情亚洲 | 国内av自拍 | 亚洲视频在线播放 | 边吃奶边添下面好爽 | 欧美日韩tv | 爽天天天天天天天 | 91高清国产 | 亚洲一区国产一区 | 超碰人人超碰 |