Linux内核Socket CAN中文文档 联系客服

发布时间 : 星期一 文章Linux内核Socket CAN中文文档更新完毕开始阅读c7eae43b5a8102d276a22f91

Linux内核Socket CAN中文文档

分类: linux驱动2012-01-30 16:26 1301人阅读 评论(2) 收藏 举报

自己在年假中空闲之余翻译的内核中Socket CAN的文档,原文地址在:

http://lxr.linux.no/linux+v2.6.34/Documentation/networking/can.txt

但是这篇文档没有涉及广播管理协议套接字 (SOCK_DGRAM) 的内容。 另外一篇比较好的Socket CAN的英文文档是(详细介绍了广播管理协议套接字):

Low Level CAN Framework Application Programmers Interface

http://www.brownhat.org/docs/socketcan/llcf-api.html#SECTION00051000000000000000 自己暂时没时间翻译这篇文章了,有空再说吧。

自己英文水平有限,希望高人指正。

================================================================================

这篇文章主要针对can协议簇(aka socket can) 这篇文章包含以下内容: ===============

1 概述--什么是Socket CAN?

2 动机--为什么使用socket API接口?

3 Socket CAN详解 3.1 接收队列 3.2 发送帧的本地回环 3.3 网络安全相关 3.4 网络故障监测

4 如何使用Socket CAN

4.1 使用can_filter的原始套接字 (RAW socket) 4.1.1 原始套接字选项 CAN_RAW_FILTER 4.1.2 原始套接字选项 CAN_RAW_ERR_FILTER

4.1.3 原始套接字选项 CAN_RAW_LOOPBACK 4.1.4 原始套接字选项 CAN_RAW_RECV_OWN_MSGS 4.2 广播管理协议套接字 (SOCK_DGRAM) 4.3 面向连接的传输协议 (SOCK_SEQPACKET) 4.4 无连接的传输协议 (SOCK_DGRAM)

5 Socket CAN核心模块 5.1 can.ko模块的参数 5.2 procfs接口

5.3 写一个自己的CAN协议模块

6 CAN网络驱动 6.1 常见设置 6.2 发送帧的本地回环 6.3 CAN控制器的硬件过滤 6.4 虚拟的CAN驱动 (vcan) 6.5 CAN网络设备驱动接口

6.5.1 Netlink接口--设置/获取设备属性 6.5.2 设置CAN的比特_时序 6.5.3 启动和停止CAN网络设备 6.6 支持Socket CAN的硬件

7 学习Socket CAN的相关资源

8 贡献者名单

==============现在开始=================== 1. 概述--什么是Socket CAN? ==================

socketcan子系统是在Linux下CAN协议(Controller Area Network)实现的一种实现方法。 CAN是一种在世界范围内广泛用于自动控制、嵌入式设备和汽车领域的网络技术。Linux下最早使用CAN的方法是基于字符设备来实现的,与之不同的是Socket CAN使用伯克利的socket接口和linux网络协议栈,这种方法使得can设备驱动可以通过网络接口来调用。

Socket CAN的接口被设计的尽量接近TCP/IP的协议,让那些熟悉网络编程的程序员能够比较容易的学习和使用。

2. 动机--为什么使用socket API接口? =======================

在Socket CAN之前Linux中已经有了一些CAN的实现方法,那为什么还要启动Socket CAN这个项目呢?大多数已经存在的实现方法仅仅作为某个具体硬件的设备驱动,它们往往基于字符设备并且提供的功能很少。那些方案通常是由一个针对具体硬件的设备驱动提供的字符设备接口来实现原始can帧的发送和接收,并且直接和控制器硬件打交道。帧队列和ISO-TP这样的高层协议必须在用户空间来实现。就像串口设备接口一样,大多数基于字符设备的实现在同一时刻仅仅支持一个进程的访问。如果更换了CAN控制器,那么同时也要更换另一个设备驱动,并且需要大多数应用程序重新调整以适应新驱动的API。

Socket CAN被设计用来克服以上种种不足。这种新的协议族实现了用户空间的socket接口,它构建于Linux网络层之上,因此可以直接使用已有的队列功能。CAN控制器的设备驱动将自己作为一个网络设备注册进Linux的网络层,CAN控制器收到的CAN帧可以传输给高层的网络协议和CAN协议族,反之,发送的帧也会通过高层给CAN控制器。传输协议模块可以使用协议族提供的接口注册自己,所以可以动态的加载和卸载多个传输协议。事实上,CAN核心模块不提供任何协议,也不能在没有加载其它协议的情况下单独使用。同一时间可以在相同或者不同的协议上打开多个套接字,可以在相同或者不同的CAN ID上同时监听和发送(listen/send)。几个同时监听具有相同ID帧的套接字可以在匹配的帧到来后接收到相同的内容。如果一个应用程序希望使用一个特殊的协议(比如ISO-TP)进行通信,只要在打开套接字的时候选择那个协议就可以了,接下来就可以读取和写入应用数据流了,根本无需关心CAN-ID和帧的结构等信息。

使用字符设备也可以让用户空间获得类似的便利,但是这中解决方案在技术上不够优雅,原因如下:

*复杂的操作。使用Socket CAN,只需要向socket(2)函数传递协议参数并使用bind(2)选择CAN接口和CAN ID,基于字符设备实现这样的功能却要使用ioctl(2)来完成所有的操作。

*无法代码复用。字符设备无法使用Linux的网络队列代码,所以必须为CAN 网络重写这部分功能。

*缺乏抽象性。在大多数已经实现的字符设备方案中,硬件相关的CAN控制器设备驱动直接提供应用程序需要的字符设备。在Unix系统中,无论对于字符设备还是块设备,这都是不常见的。比如,你不会为某个串口、电脑上的某个声卡、访问磁带和硬盘的SCSI/IDE控制器直接创建一个字符设备。相反,你会将向应用程序提供统一字符设备/块设备接口的功能交给一个抽象层来做,你自己仅仅提供硬件相关的设备驱动接口。这种抽象是通过子系统来完成的,比如tty层子系统、声卡子系统和SCSI/IDE子系统。

实现CAN设备驱动最简单的办法就是直接提供一个字符设备而不使用(或不完全使用)抽象层,大多数已经存在的驱动也是这么做的。但是正确的方法却要增加抽象层以支持各种功能,如注册一个特定的CAN-ID,支持多次打开的操作和这些操作之间的CAN帧复用,支持CAN帧复杂的队列功能,还要提供注册设备驱动的API。然而使用Linux内核提供的网络框架将会大大简化,这就是Socket CAN要做的。

在Linux中实现CAN功能最自然和合适的方式就是使用内核的网络框架。

3. Socket CAN详解 ============

就像第二章所讲的那样,使用Socket CAN的主要目的就是为用户空间的应用程序提供基于Linux网络层的套接字接口。与广为人知的TCP/IP协议以及以太网不同,CAN总线没有类似以太网的MAC层地址,只能用于广播。CAN ID仅仅用来进行总线的仲裁。因此CAN ID在总线上必须是唯一的。当设计一个CAN-ECU(Electronic Control Unit 电子控制单元)网络的时候,CAN-ID可以映射到具体的ECU。因此CAN-ID可以当作发送源的地址来使用。

3.1 接收队列 ---------------

允许多个应用程序同时访问网络导致了新的问题出现,那就是不同的应用程序可能会在同一个CAN网络接口上对具有相同CAN-ID的帧感兴趣。Socket CAN的核心部分实现了Socket CAN的协议族,通过高效的接收队列解决了这个问题。比如一个用户空间的程序打开了一个原始CAN套接字,原始协议模块将向CAN套接字的核心模块申请用户空间需要的一系列CAN-ID。Socket CAN的核心向CAN协议模块提供预约和解约CAN-ID的接口--can_rx_(un)register(),无