2008年7月25日星期五

学习kernel网络体系结构(3)

尽管,现在开始学习内核,我感觉自己的基础还是很不好的,没有进行一些系统的学习,而且基础部分也是七零八散的。没有把过去学到运用起来。所以现在还是以学习基础为主,不要好高骛远了!
这次主要写的是关于net的也就是说很多函数在dirvers/net/下还有在net/core/下
除了字符设备和块设备,网络设备是Linux内核中的第三类适配器。他们在设备文件系统/dev/中没有表示,这就意味着不能通过简单的读写来操作来访问他们。网络适配器不能被邦定到单个进程,他们运行在内核中并且独立于各用户进程[RuCo01]。
顺便添加几本好的书哦![RuCo01] Alessandro Rubini and Jonathan Corbet. Linux Device Drivers. Sebastopol, CA: O'Reilly & Associates, 2d ed., 2001. Online version at http://www.oreilly.com/catalog/linuxdrive2/index.html. (Visited on January 10, 2004.)
[BBDK+01] Michael Beck, Harald Böhme, Mirko Dziadzka, Ulrich Kunitz et al. Linux Kernel Programming. Boston: Addison-Wesley, 3d ed., 2002.
[BoCe00] Daniel P. Bovet and Marco Cesati. Understanding the Linux Kernel. Beijing and Cambridge, MA: O'Reilly, 2000
有空要看看哦!
我在include/linux/netdevice.h 这个目录下看net_device结构,此结构是内核中的所有网络设备的基础数据结构。它不仅包含网络适配器的硬件信息(中断,端口,驱动程序函数等等),还包括面向更高层网络协议的网络设备配置数据(IP地址,子网掩码等)。其中包含了大量的函数指针,更高层协议通过它们的全局名称来调用它们,随后驱动程序的硬件相关方法被各网络设备调用。

我认为还是先大体浏览一边而后在进行,认识细致的读和理会,它们中的每一个数据结构的意思都要明白和了解。

现在,大体把其中的主要的部分列举,它们中有网络设备的通用字段;硬件相关字段;网络层上的字段。Linux内核中的所有网络设备都被一个线性表连接起来。
网络设备的注册与注销,哦,drivers/net/net_init.c这个文件竟然在2.6.26中没有找到。
MAC协议(FDDI,HIPPI),难道是媒体介质访问控制(Medium Access Control,MAC)协议,应该看看了。
网络设备的开启和关闭,相关代码在net/core/dev.c下,同样,创建和寻找网络设备的代码,还有为状态改变而设计的通知链,在网络设备上进行传输,网络设备中的初始化网络适配器。
分配系统资源的帮助者函数
request_region() , release_region() , check_region()在kernel/resource.c下
request_irq() , free_irq()在kernel/irq.c下
request_dma() , free_dma()在kernel/dma.c下
但是,打开和关闭网络适配器,传输数据,包传输过程的问题,运行配置,适配器相关的ioctl()命令,网络设备的统计信息,适配器层次的多播支持,的主要函数在drivers/net/isa_skeleton.c下

sctp协议

几个相关的网站
http://www.ibm.com/developerworks/cn/linux/l-sctp/
http://www.ietf.org/
你应该下载相关的,软件才可以用。
http://sourceforge.net/projects/lksctp
他的相关的文档
http://www.ietf.org/rfc/rfc2960.txt
在以后的通信领域里面应该会比较多的应用sctp协议。
以后,看看,现在还是看一些简单的!
The Stream Control Transmission Protocol (SCTP) is a new IP transport protocol, existing at an equivalent level with UDP (User Datagra Protocol) and TCP (Transmission Control Protocol), which provide transport layer functions to many Internet applications. SCTP has been approved by the IETF as a Proposed Standard [1]. The error check algorithm has since been modified [2]. Future changes and updates will be reflected in the IETF RFC index.

2008年7月24日星期四

学习kernel网络体系结构(2)

尽管,看过了,但是还是不能深刻的记忆和理解,我感觉只有一步一步的实践了之后,你才会正真的理解其中的奥秘。我再次,重新看。Linux网络实现的灵活性和高效性的一个主要因素是缓冲体系结构,它管理了网络报文——所谓的套接字缓存(socket buffer) ,skb。
一个套接字缓存由俩部分组成:报文数据和管理数据。

看了这个图,我们将分析他们中的一些具体的参数。
我们要明白其中的指针指向的位置。

其实,内容很多,我们还是简单的了解一些,而后多读源代码,现在把一些代码粘贴,看看,那些和图里面是如何对应的。
自 2.6.22 版的核心開始,sk_buff 結構變更

struct sk_buff_head {
/* These two members must be first. */
struct sk_buff *next;
struct sk_buff *prev;
__u32 qlen;
spinlock_t lock;
};
但是,下面的和以前一些版本有些变化。
struct sk_buff {
/* These two members must be first. */
struct sk_buff *next;
struct sk_buff *prev;

struct sock *sk;
ktime_t tstamp;
struct net_device *dev;

union {
struct dst_entry *dst;
struct rtable *rtable;
};
struct sec_path *sp;

char cb[48];

unsigned int len,
data_len;
__u16 mac_len,
hdr_len;
union {
__wsum csum;
struct {
__u16 csum_start;
__u16 csum_offset;
};
};
__u32 priority;
__u8 local_df:1,
cloned:1,
ip_summed:2,
nohdr:1,
nfctinfo:3;
__u8 pkt_type:3,
fclone:2,
ipvs_property:1,
peeked:1,
nf_trace:1;
__be16 protocol;

void (*destructor)(struct sk_buff *skb);
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct nf_conntrack *nfct;
struct sk_buff *nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
#endif

int iif;
#ifdef CONFIG_NETDEVICES_MULTIQUEUE
__u16 queue_mapping;
#endif
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
__u16 tc_verd; /* traffic control verdict */
#endif
#endif
#ifdef CONFIG_IPV6_NDISC_NODETYPE
__u8 ndisc_nodetype:2;
#endif
/* 14 bit hole */

#ifdef CONFIG_NET_DMA
dma_cookie_t dma_cookie;
#endif
#ifdef CONFIG_NETWORK_SECMARK
__u32 secmark;

#endif

__u32 mark;

sk_buff_data_t transport_header;
sk_buff_data_t network_header;
sk_buff_data_t mac_header;
/* These elements must be at the end, see alloc_skb() for details. */
sk_buff_data_t tail;
sk_buff_data_t end;
unsigned char *head,
*data;
unsigned int truesize;
atomic_t users;
};
套接字缓存是用来定位和管理一个报文在内核中被处理的整个周期的。
以上的代码都是在include/linux/skbuff.h 里面,有空在好好的看看其他的。
struct sk_buff可能是linux网络代码中最重要的数据结构,它表示接收或发送数据包的包头信息,并包含很多成员变量供网络代码中的各子系统使用。
这个结构被网络的不同层(MAC或者其他二层链路协议,三层的IP,四层的TCP或UDP等)使用,并且其中的成员变量在结构从一层向另一层传递时改变。 L4向L3传递前会添加一个L4的头部,同样,L3向L2传递前,会添加一个L3的头部。添加头部比在不同层之间拷贝数据的效率更高。由于在缓冲区的头部 添加数据意味着要修改指向缓冲区的指针,这是个复杂的操作,所以内核提供了一个函数skb_reserve来完成这个功能。协议栈中的每一层在往下一层传 递缓冲区前,第一件事就是调用skb_reserve在缓冲区的头部给协议头预留一定的空间。
skb_reserve同样被设备驱动使用来对齐接收到包的包头。如果缓冲区向上层协议传递,旧的协议层的头部信息就没什么用了。例如,L2的头部只有在 网络驱动处理L2的协议时有用,L3是不会关心它的信息的。但是,内核并没有把L2的头部从缓冲区中删除,而是把有效荷载的指针指向L3的头部,这样做, 可以节省CPU时间。
http://hi.baidu.com/zkheartboy/blog/item/2dd5207a28eb2fee2f73b355.html不错哦!
Linux内核为我们提供了很多函数来操作套接字缓存,如:1.创建,释放和复制套接字缓存 2.操作sk_buff结构里的参数和指针 3.管理套接字缓存队列
而这些函数一般在net/core/skbuff.c 和include/linux/skbuff.h函数中。

进程fork

学习了一段时间进程,用fork()函数把原来的进程,变为俩个进程,其实就是fork()创建了一个新的进程,新进程返回"0",原来的进程继续执行,返回一个新的PID。
在man手册中说fork create a child process
SYNOPSIS:梗概
#include
#include
pid_t fork(void);
看这是什么呢?pid_t是在types.h这个文件下的
pid_t Used for process IDs and process group IDs.
而fork()函数在unistd.h下定义了,而且还有 pid_t vfork(void);

DESCRIPTION: fork() creates a new process by duplicating the calling process. The new process, referred to as the child, is an exact duplicate of the calling process, referred to as the parent, except for the following points:
SEE ALSO
clone(2), execve(2), setrlimit(2), unshare(2), vfork(2), wait(2), capa-
bilities(7), credentials(7)
也就是说我们也要看这些相关的函数,才可以更好的理解和运用fork()函数。
进程是正在运行的程序,其实他是一个运行着一个或者多个线程的地址空间和这些线程所需
的系统资源。每一个进程将会被分配一个PID。进程有自己的栈空间,用于保存函数中的局>部变量和控制函数的调用与返回。进程还有自己的环境空间,包含专门为这个进程建立的环
境变量。进程还必须维护自己的程序计数器,这个计数器用来记录他执行到的位置,即执行
线程中的位置。
Linux进程表就像一个数据结构,它把当前加载在内存中所有进程的有关信息保存在一个表>中,其中包括进程的PID,进程的状态,命令字符串和其他一些ps命令输出的各类信息。每>个进程都是由一个我们称之为“父进程”的进程启动的,被父进程启动的进程叫做子进程。系
统运行的第一个进程是init进程启动的,它是其他所有进程的祖先进程。
Linux调度器以进程的优先级为基础来决定运行哪个进程。
等待一个进程用wait()
子进程终止时,它还与父进程之间的关联还会保持,直到父进程也完全结束或者是调用wait
才告结束。因此,在进程表中子进程不会立刻被释放。虽然子进程的不再运行,但是它仍然
存在于系统之中,它的退出码还需要保存起来以备父进程今后的wait调用,这时它将成为一
个死进程或者是僵死进程。
* The child has its own unique process ID, and this PID does not
match the ID of any existing process group (setpgid(2)).

* The child’s parent process ID is the same as the parent’s process
ID.

* The child does not inherit its parent’s memory locks (mlock(2),
mlockall(2)).

* Process resource utilizations (getrusage(2)) and CPU time counters
(times(2)) are reset to zero in the child.

* The child’s set of pending signals is initially empty (sigpend-
ing(2)).
* The child does not inherit semaphore adjustments from its parent
(semop(2)).

* The child does not inherit record locks from its parent (fcntl(2)).

* The child does not inherit timers from its parent (setitimer(2)
alarm(2), timer_create(3)).

* The child does not inherit outstanding asynchronous I/O operations
from its parent (aio_read(3), aio_write(3)).

The process attributes in the preceding list are all specified in
POSIX.1-2001. The parent and child also differ with respect to the
following Linux-specific process attributes:

gdb调试

今天,学习gdb调试,每一天都要有自己的计划。
在用gcc编译的时候就应当添加-g这个选项的。比如:$ gcc -g -o useupper useupper.c
然后你就进入到了(gdb) 你就可以输入命令了,如输入list
当然,我们一般还有设置一些断点,看看我们的程序运行到那里有什么问题,用break命令。(gdb) help break就可以看到他的详细信息了。然后当然用到next和step的命令了,他们的对比如下:
(gdb) help next
Step program, proceeding through subroutine calls.
Like the "step" command as long as subroutine calls do not happen;
when they do, the call is treated as one instruction.
Argument N means do this N times (or till program stops for another reason).
(gdb) help step
Step program until it reaches a different source line.
Argument N means do this N times (or till program stops for another reason).
我们也可以不一步一步用next和step的命令执行我们的代码,而是要直接执行到n行为止,那我们就用until命令吧!用print命令可以查看变量的值。有时可用finish继续执行直到目前的函数结束。
(gdb) help finish
Execute until selected stack frame returns.
Upon return, the value returned is printed and put in the value history.
命令backtrace和bt和where是一样的
(gdb) help bt
Print backtrace of all stack frames, or innermost COUNT frames.
With a negative argument, print outermost -COUNT frames.
Use of the 'full' qualifier also prints the values of the local variables.
我们也可以用display命令告诉 gdb,在每次程序停止在断点位置时自动显示数组的内容。
(gdb) commands我们用这个命令可以修改断点设置,不在断点处停下而是显示,然后继续执行。
Type commands for when breakpoint 2 is hit, one per line.
End with a line saying just "end".
>cont
>end
这里还可以设置其他的一些,如为了打补丁,改变变量用set variable 变量
而cont命令是
Continue program being debugged, after signal or breakpoint.
If proceeding from breakpoint, a number N may be used as an argument,
which means to set the ignore count of that breakpoint to N - 1 (so that
the breakpoint won't break until the Nth time it is reached).
我们可以用info查看一些信息,比如说查看断点及display命令的内容。
我们可以用disable来禁用我们过去的设置。
其他调试工具:
ctags,cxref和cflow等就是一些静态分析程序,他们可以通过源文件提供有关函数调用和函数所在位置的有用信息。prof和gprog等就是一些动态分析程序,他们提供的信息包括已经执行了哪些函数以及这些函数的执行时间。

2008年7月23日星期三

C语言

EOF ( end of file 文件结束标记 )

exit(int Code)中的Code是子进程交给父进程的退出码,父进程由此可以判断子进程的工作状态,比如 nmake(或make,项目管理程序)和cc(或cl,C编译器)的关系, cc就是make的子进程.如果编译成功,cc就用exit(0),父进程make得到这0之后,继续 做后面的事,如果编译失败,cc就用exit(-1),父进程make得到这个-1后,立即停止项目管理,让程序员查错.不管exit的参数是什么,只要调用就一定退出。

extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。extern用在变量声明中常常有这样一个作用,你在*.c文件中声明了一个全局的变量,这个全局的变量如果要被引用,就放在*.h中并用extern来声明。如果函数的声明中带有关键字extern,仅仅是暗示这个函数可能在别的源文件里定义,没有其它作用。即下述两个函数声明没有明显的区别:当然,这样的用处还是有的,就是在程序中取代include “*.h”来声明函数,在一些复杂的项目中,我比较习惯在所有的函数声明前添加extern修饰。

枚举的说明与结构和联合相似, 其形式为:
enum 枚举名{
标识符[=整型常数],
标识符[=整型常数],
...
标识符[=整型常数],
} 枚举变量;

2008年7月22日星期二

学习kernel网络体系结构(1)

最近在看The Linux Network Architecture其实这本书的名字很长的我就简写了。
学习内核,文件系统很重要,因为Linux内核中几乎所有项目都是通过文件系统接口加以处理的。
内核分为:整体式内核,微内核。
Linux是采用整体式内核的,但是2.0开始把某些功能变成了模块;可载人内核也可移出内核。
模块化的好处:接口的定义会始终如一。
在linux-2.6/net的目录下有很多关于网络方面的源代码,在linux-2.6/Documentation/networking目录下也很多的相关的文档是不是也要读一读呢?应该的,至少在暑假期间把这些都看一遍的。
[RuCo01] [BBDK+01] [BoCe00]这些资料应该看看。
学习网络,我们应该知道ISO/OSI参考模型,虽然它们现在用的不是很广泛但是对我们理解网络还是很有忙助的。

这边是模型图,但是现在应用比较多的还是TCP/IP,在看看它们的对比。好好观测它们之间的不同,和相同的地方,还有就是TCP/IP的优点。每一层之间的关系,和下一层,还有上一层的关系。

今天,感觉理解了服务和协议。我就简单的介绍一下。
一些预定义的规则控制不同计算机上相同层的俩个实例之间的通信,这些规则被称为协议。
一个层(第N层)向更高的层(第N+1层)提供一个功能集合,这个功能集合被称为服务。
我们也就是要理解同层与同层之间的关系,不同层与不同层之间的关系。
* 应用层 (Application):应用层是个很广泛的概念,有一些基本相同的系统级 TCP/IP 应用以及应用协议,也有许多的企业商业应用和互联网应用。
* 传输层 (Transport):传输层包括 UDP 和 TCP,UDP 几乎不对报文进行检查,而 TCP 提供传输保证。
* 网络层 (Network):网络层协议由一系列协议组成,包括 ICMP、IGMP、RIP、OSPF、IP(v4,v6) 等。
* 链路层 (Link):又称为物理数据网络接口层,负责报文传输。

好!明天继续!

time