求教,linux下网口虚拟串口驱动程序

作者&投稿:挚果 (若有异议请与网页底部的电邮联系)
linux下如何使用虚拟串口的usb设备~

usb转串口设备需要单独安装驱动的,如果没有驱动,当然无法识别了

  虚拟机中的串口连接可以采用两种方法。一种是指定虚拟机的串口连接到实际的COM上,例如开发机连接到COM1,目标机连接到COM2,然后把两个串口通过串口线相连接。另一种更为简便的方法是:在较高一些版本的VMware中都支持把串口映射到命名管道,把两个虚拟机的串口映射到同一个命名管道。例如,在两个虚拟机中都选定同一个命名管道 \\.\pipe\com_1,指定target机的COM口为server端,并选择"The other end is a virtual machine"属性;指定development机的COM口端为client端,同样指定COM口的"The other end is a virtual machine"属性。对于IO mode属性,在target上选中"Yield CPU on poll"复选择框,development机不选。

开发虚拟串口驱动程序

虚拟串口就是当本地并没有对应的串口硬件设备,而为应用层提供串口设备一样的系统调用接口,以兼容原本使用本地串口的应用软件的“虚”设备。本文作者给出了一种在Windows平台上实现虚拟串口的方法,由此实现的“串口”具有真实串口完全相同的系统调用接口。
在很多应用中需要用到虚拟串口,如在Modem卡出现之前,已经有了接在计算机串口上的外部Modem,而且各种拔号程序也是通过串口与外部Modem通信的。为了让已有的拔号程序不做修改,像使用外部Modem一样使用内置卡,就需要内置卡的驱动程序虚拟一个串口设备。又如当前工业界使用的一些串口服务器,往往有8个或16个甚至更多的串口,以连接多个串口设备,再通过一个网卡直接连入以太网。与它在同一网络上的计算机就通过以太网与串口服务器上挂接的串口设备通信。为了让计算机中原来使用本地串口的软件兼容,就需要在计算机上提供虚拟串口驱动。
虚拟串口的设计关键在于,该“串口”实现后必须具有与真实串口完全相同的系统调用接口。要做到这点,从已有的串口设备驱动程序上做修改是最佳捷径。下文就介绍以Windows NT上的串口驱动程序为基础,开发可运行于Windows NT、Windows 2000、Windows XP的各个版本虚拟串口驱动程序。
串口驱动中使用的几个链表
由于串口是双工设备,在一个读请求发出来还没有完成之前,同时可以发出写请求,加上在驱动程序层所有I/O请求都要求异步完成,即前一个请求尚没有完成,下一个相同的请求可能又来了。为此,串口驱动程序需要使用多个双向链表数据结构来处理各种IRP(I/O Request Packet,I/O请求包)。当收到一个IRP,先判断是否可立即完成,可以马上处理并返回,如果不允许则将IRP插在相应链表尾,在适当的时候如设备有空闲时处理,这时往往会产生一个硬件中断,激发DPC(Deferred Procedure Call,暂缓过程调用)过程,由DPC处理函数逐个从链表头取出IRP并试着完成它。串口驱动中有以下几个链表和DPC(在serial.h中有定义):
ReadQueue 和 CompleteReadDpc
用于保存Read IRP的链表和用于调度的DPC,与DPC对应的处理函数是SerialCompleteRead,它在read.c文件中,该函数的主要任务就是从ReadQueue中提取下一个IRP,并试着完成它。
WriteQueue 和 CompleteWriteDpc
用于保存Write IRP的链表和对应的DPC,与DPC对应的函数是SeriaCompleteWrite,它的实现在write.c中,该函数负责从WriteQueue中提取IRP,并试着完成它。
MaskQueue 和 CommWaitDpc
这一对链表用于处理Windows串口驱动的一个特性:事件驱动机制。它允许应用程序预设一个事件标志,而后等待与标志对应事件发生。DPC所调用的函数是SerialCompleteWait,它实现在Waitmask.c文件中,该函数也是试着从MaskQueue中提取IRP并完成它。
PurgeQueue
该链表与前面几个稍有不同,它没有与之相对应的DPC机制,而是在每次收到Purge请求时从PurgeQueue中逐个提取IRP并试着完成,因某种原因不能完成时则插入链表。相应的函数是purge.c文件中的SerialStartPurge。
以上机制是串口驱动程序的重要实现方法,在虚拟串口驱动中需要保留,但不同的是,硬件串口驱动中是ISR(中断服务程序)根据收、发或MODEM中断来激发相应的DPC,而在虚拟串口驱动中将因实际情况不同会有不同的激发机制。
DriverEntry的实现
DriverEntry是驱动程序的入口函数,相当于应用程序C语言中的main函数,开发一个虚拟串口驱动首先要修改的就是它。它的函数实体在initunlo.c文件中。只是在虚拟串口驱动中由于不与具体的硬件打交道,就不存在硬件资源分析、硬件初始化、判断其工作状态等处理,只需要为虚拟串建立设备对象、符号链接和初始化数据结构。一个典型函数实现大体如下:
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
/*填写DriverObject->MajorFunction[]数组*/
/*建立设备对象*/
/*初始化SERIAL_DEVCIE_EXETENSION数据结构*/
Status = IoCreateDevice(DriverObject, sizeof(SERIAL_DEVICE_EXTENSION), &uniNameString, FILE_DEVICE_SERIAL_PORT, 0,TRUE,&deviceObject);
//初始化所有链表
InitializeListHead(&extension->ReadQueue);
InitializeListHead(…);
…;
//初始化所有DPC
KeInitializeDpc(&extension->CompleteReadDpc,SerailCompleteRead,extension);
KeInitializeDpc(…);
/*建立符号链接*/
SerialSetupExternalNaming(extension);
return Status;
}
SerialRead和SerialCompleteRead的实现
函数SerailRead和SerialCompleteRead决定了对Read IRP的响应策略,它们都存于read.c中。以串口服务器要用的虚拟串口为例,当串口服务器收到来自外部数据时将通过网络发至计算机,计算机则产生相应的网络中断并进行协议数据处理。网络接收线程缓存新收到的数据并激活CompleteReadDpc,从而SerialCompleteReadIrp得到调用,它再调用CompleteReadIrp对每个IRP进行处理。它们的实现大体如下:
NTSTATUS SerialRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
/*此处略去变量声明和初始化*/
/*提取IRP中相关的数据*/
stack = IoGetCurrentIrpStackLocation(Irp);
ReadLen = stack->Parameters.Read.Length;
/*先看本地缓冲有数据否?有的话先读取*/
if(Extension->InCounter > 0 )
{ //注意这里要加锁,以防数据访问冲突
KeAcquireSpinLock(&Extension->
ReadBufferLock,&lIrql);
FirstRead = (ReadLen>Extension->
InCounter)? Extension->InCounter: ReadLen;
RtlCopyMemory(Irp->AssociatedIrp.
SystemBuffer,Extension->pInBuffer,FirstRead);
Extension->InCounter -= FirstRead;
ReadLen -= FirstRead;
KeReleaseSpinLock(&Extension->
ReadBufferLock,lIrql);//释放锁
}
/*是否已读到足够数据?是的话则完成该IRP*/
if( 0 == ReadLen)
{
status=STATUS_SUCCESS;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = FirstRead;
IoCompleteRequest(Irp,0);
return status;
}
/*没有则将IRP插入队列中,通过网络向串口服务器发出读数据请求*/
IoMarkIrpPending(Irp);
InsertWaitList(Extension->ReadQueue,Irp);
status = TdiSendAsync(Extension->ComChannel,pAckPacket,PacketLen(pAckPacket),(PVOID)ReadAckComplete,Irp);
/*返回PENDING,表示该IRP尚没有完成*/
return STATUS_PENDING;
}
Void CompleteReadIrp(IN PSERIAL_DEVICE_EXTENSION extension,IN PIRP Irp,IN PUCHAR pInData,IN ULONG Length )
{
/*此处略去变量声明和初始化*/
/*读取新数据*/
ReadLen = (ReadLen > Length)? Length : ReadLen;
if(ReadLen != 0)
{
RtlCopyMemory(pReadAsync->
pReadBuffer,pInData,ReadLen);
pReadAsync->pReadBuffer += ReadLen;
pReadAsync->ReadAlready += ReadLen;
extension->PerfStats.ReceivedCount +=
ReadLen;
}
else
{
/*因为串口服务器端只有在已经有了相应的数据或超过时间(此时,Length=0)才会发来应答并激活本DPC过程,所以此时已经超时,为了便于结束本IRP,这里有意改变TotalNeedRead,造成接收完毕的假象*/
pReadAsync->TotalNeedRead =
pReadAsync->ReadAlready;
}
if(pReadAsync->TotalNeedRead == pReadAsync->ReadAlready)
{
/*该IRP是否已经接收完毕,是的话则结束该
IRP*/
EndReadIrp(Irp);
/*从ReadQueue中取下一个IRP*/
}
/*本IRP没有完成也没有超时,则继续等待本DPC下次被激活,注意此时要判断IRP是否被要求取消*/
}
SerialWrite和SerailCompleteWrite的实现
SerialWrite和SerailCompleteWrite决定了Write IRP的实现。在SerialWrite中调用了网络发送函数TdiSendAsync,当该发送完成后将激活CompleteWriteDpc,调度SerialCompleteWrite函数,而它主要就是取出当前的WriteIRP,设置已经发送的数据数量,调用CompleteWriteIrp做该IRP的进一步处理。它们大体如下:
NTSTATUS SerialWrite(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
/*此处略去变量声明和初始化*/
/*从IRP中提取有关数据*/
stack=IoGetCurrentIrpStackLocation(Irp);
SendLen = stack->Parameters.Write.Length;
/*为网络发送和异步操作分配缓冲,在CompleteWrite中全部数据发送完后释放*/
pWriteAsync = ExAllocatePool(NonPagedPool,
SendLen+PACKET_HEADER_LEN+sizeof(WRITE_ASYNC));
if(pWriteAsync == NULL)
{
//错误处理
}
//保存异步数据

//设置网络发送数据包
BuildDataPacket(pPacket,WRITE,(USHORT)SendLen,pWriteAsync->pWriteBuffer);
/*先将IRP暂时阻塞并插入队列,在CompleteWrite中完成*/
IoMarkIrpPending(Irp);
InsertWaitList(extension->WriteQueue, Irp);
/*将写请求和相关数据通过网络发向串口服务器,由它负责将数据传到具体串口设备*/
status = TdiSendAsync(Extension->ComChannel,pPacket,PacketLen(pPacket),(PVOID)CompleteWriteIrp,Irp);
//统计数据累加
Extension->PerfStats.TransmittedCount += SendLen;
return STATUS_PENDING;
}

NTSTATUS CompleteWriteIrp(IN PDEVICE_OBJECT deviceobject,IN PIRP pIrp,IN PVOID context)
{
/*此处略去变量声明和初始化*/
SendLen=pWriteAsync->TotalNeedWrite - pWriteAsync->WroteAlready;
if(SendLen == 0)//全部数据发送完毕
{
EndWaitWriteIrp(pWriteIrp,STATUS_SUCCESS,
pWriteAsync->WroteAlready,pWriteAsync);
//从WriteQueue中取下一个IRP;
}
else //发送剩余数据
{
if(pWriteIrp->Cancel)
{
//IRP被要求取消,完成WriteIrp
EndWaitWriteIrp(pWriteIrp,STATUS_CANCELLED,
pWriteAsync->WroteAlready,pWriteAsync);
return STATUS_CANCELED;
}
else
{
//再次设置网络数据包并发送
BuildDataPacket(…);
status = TdiSendAsync(…);
//统计数据累加
Extension->PerfStats.TransmittedCount +=
SendLen;
return STATUS_MORE_PROCESSING_REQUIRED;
}
}
}
其他几个接口函数的实现
除Read/Write外,SerialUnload、SerialCreateOpen、 SerialClose、SerialCleanup、SerailFlush等调用接口是硬件相关性比较弱的接口函数,基本不要修改,直接删除原来操作硬件的部分即可。复杂一点就是SerialIoControl,该接口函数包含有大量设置、读取串口硬件状态的处理,可建立一个本地数据结构随时保存虚拟串口的当前硬件状态。同时为了保证串口服务器端的真实串口状态和上层软件要求的一致,需要将所有设置请求通过网络发送到服务器端,由它负责改变真实硬件的状态。


Linux下设置可使用netpas网络加速器的方法与步骤介绍
但这里 都有一个问题,那就是所有的网络加速服务都只有windows下的客户端,在 linux就都没有官方的使用方法了。对有些加速服务,有人想出了一些非官方的 办法,比如在知道服务器地址的前提下,教育网直通车可以用PPPoE来连。据说,BrigeWan也可以用类似的方法,但上次在一个论坛里看到因为官网对协议作了点小修改,结果...

跪求一份linux下网络编程的学习心得
不过内容有些杂乱,如果您没有一些写驱动的经验,初次看会有些摸不着南北。国内翻译的是《Linux设备驱动程序》第二版,第一版,第二版的译者我都有很深的接触,不过总体上来说,虽然第二版翻译的有些不尽人意,但是相比第一版来说已经超出了一大截。要读这一本书,至少应该先找一些《计算机原理》...

Linux基础教程linux教程下载
请问,如何在linux里下载文件?1。不需要开FTP 2。在LINUX下有multiget,Kget,wget,D4X,浏览器还有个DOWNTHEMALL,还有proz等等,当然也可以用wine装迅雷下载。3。linux里文件后缀名,我们常见的rpm,deb,tar.gz,bz,bz2等等,tar:tar包(不压缩的)tar.gz和tar.bz2:tar包,第一个gnuzip压缩的,...

linux基础教程
二、Linux系统安装与启动 1. 安装Linux:可以通过多种途径安装Linux,如使用Live CD\/USB、虚拟机或通过发行版的官方安装程序。选择合适的安装版本和分区方案后,按照提示操作即可完成安装。2. 启动与关机:Linux系统启动后,会经历自检、加载内核、显示登录界面等过程。关机时可以使用shutdown命令或者通过图形...

Linux系统下动态DNS服务的详细配置教程
在网络管理中,对于DNS服务的管理是一项基础性的工作。随着用户规模的扩大,频繁地手工修改DNS的区域数据库文件不是一件轻松的工作。关于动态DNS(DDNS)的研究逐渐引起了人们的关注,不同的平台都推出了自己的解决方案。本文将详细介绍Linux环境下DDNS的解决方案,即由Internet Software Consortium(ISC)开发的...

linux双网服务器架设教程(高分求)
LINUX下双网双线服务器的架设全过程目的: 现在很多中小型网络有两条或者多条相同的不同的ISP的网络出口线路而如何将这两条线路合理的利用起来 是很多人非常关心的西安秀网吧资讯会为大家提供更多更好的学习资料和知 此文用通俗易懂的方法的讲解了如何初步达到此目的 本方案不需要大量的投资 也不需要改变现有网络结构...

请教Linux系统下DHCP问题..
这儿我解释一下配置部分,首先subnet定义了网络的地址,然后option routers定义了网关地址;subnet-mask定义子网掩码;broadcast-address定义广播地址;domain-name-servers定义DNS NAMESERVER的地址;dynamic-bootp是给客户端分配的地址,定义的是192.168.0.1-- 192.168.0.255整个网段地址;最后2行是讲分配...

linux系统下载安装的教程
首先,启动虚拟机,点击“创建新的虚拟机”选项,开始你的Linux系统安装过程。在创建过程中,选择“自定义”模式,以便更好地配置你的虚拟机。在硬件配置阶段,先不急于安装系统,而是选择稍后再进行。选择Linux版本,如Red Hat Enterprise Linux 7 64位,以适应你的需求。给虚拟机起个名字,建议选择非...

学校里面LINUX不能上网,请教一下,LINUX下面可以用WINDOWS作为代理服务...
可以的.

搭建Linux系统的VPS的步骤教程
Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络 操作系统 。有用户想要在Linux上搭建vps这篇 文章 主要介绍了实例讲解搭建Linux系统的VPS的步骤,包括防火墙和SSH等基本软件的部署 方法 ,非常细致,需要的朋友可以参考下 前期准备 需要购买一台拥有 root 权限的 VPS ,我选择的是 搬瓦工 ,当时购...

长宁区19110917640: 求教,linux下网口虚拟串口驱动程序 -
邵俩盐酸: 开发虚拟串口驱动程序 虚拟串口就是当本地并没有对应的串口硬件设备,而为应用层提供串口设备一样的系统调用接口,以兼容原本使用本地串口的应用软件的“虚”设备.本文作者给出了一种在Windows平台上实现虚拟串口的方法,由此实...

长宁区19110917640: linux 怎么 在 驱动中 使用串口 -
邵俩盐酸: Linux发行版自带usb to serial驱动,以模块方式编译驱动,在内核源代码目录下运行Make MenuConfig选择Devces drivers-->USB seupport--> <M>USB Serial Converter support --> <M> USB driver for GSM and CDMA modems & [*]USB Generic Serial Driver,保存退出.运行make modules,编译成功后可找到usbtoserial.ko及option.ko两个驱动(2.6以上内核版本模块驱动用.ko表示).

长宁区19110917640: linux下无线网卡如何驱动 -
邵俩盐酸: linux下无线网卡具体驱动的操作方法如下: 1、首先需要确定网卡的类型,打开linux的输入窗口,然后继续在linux终端下输入lsusb命令,此时在输出栏的第一行可以查看网卡类型,记录下来. 2、从弹出页面可以看到的型号是relteck 5370,打...

长宁区19110917640: 如何开启VMware串口 -
邵俩盐酸: 如何开启VMware串口 先前在玩GEC2410时,有个想法,就是在linux下进行调试,由于目标板上电或复位时会发送信息给PC机的串口,这已在windows下实现过,于是想在linux下看看效果,可是当时我在linux下设好串口后,发现一点...

长宁区19110917640: stm32f103单片机的虚拟串口是否有linux下驱动 -
邵俩盐酸: 可以接串口. 如果是主板带的串口,先关闭系统,选择编辑配置,添加硬件,选择串口. 如果是USB-串口转换线缆,只要从host 上disconnect USB设备,这样USB-串口转换设备就可以在虚拟机中检测到,然后在虚拟机中加载驱动就可以.

长宁区19110917640: linux驱动:两个程序通过驱动交互数据 -
邵俩盐酸: 采用多线程方式进行管道通信交叉,也就是说,你在驱动里面设置三个thread或者更多,然后有名管道通信,试试吧.说实话,这和你的代码和实现的功能有关,只能大概的说两句,希望能够帮到你.至于分,大家都是交流技术,对那个倒是不看重.

长宁区19110917640: linux下如何使用虚拟串口的usb设备 -
邵俩盐酸: 需要驱动 pl2303 芯片的带 linux 驱动

长宁区19110917640: linux下串口驱动如何实现? -
邵俩盐酸: 用驱动程序啊 不过现在一般都能自动安装

长宁区19110917640: 用vmare虚拟机,虚拟linux下串口对联 -
邵俩盐酸: 这个方法在同一台电脑上使用两个vmare机虚拟linux,(在同一个vmare机上也可以建立两个串口对联,见文章末尾),建立一对虚拟串口,并虚拟串口联通,搭建出两机的串口通讯通路.适用于在没有串口硬件设备的情况下,调试串口通讯程...

长宁区19110917640: 你好,我把linux蓝点2.0装在IBM T30笔记本上,装完后串口无法使用,请问在LINUX下如何装串口驱动.谢谢 -
邵俩盐酸: 一般linux内核里面自带了串口驱动 你可以看一看 /dev 目录下有没有 ttyS开头的文件 一般那就是串口如果实在不行 就换更新的Linux 一般新的内核有更新的驱动

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网