文档库 最新最全的文档下载
当前位置:文档库 › ifconfig

ifconfig

===典型的用户层使用===
busybox/networking/ifconfig.c ifconfig_main()
/* Create a channel to the NET kernel. */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
bb_perror_msg_and_die("socket");
}
如果没指定ifname,则调用libbb/interface.c中display_interfaces()
同样是 调用socket()函数打开socket,获取file句柄
然后是调用 类似ioctl(skfd, SIOCGIFCONF, &ifc)的ioctl调用开始进入内核执行
===内核执行轨迹===
1.进入内核 (kernel 2.6的,2.4的类似,可能函数位置,和文件名有所不同)
该部分由libc的ioctl函数通过{某种方法}使内核进入系统调用状态。
2.内核流程
.查找对应的系统调用:
在arch下面对应的每种archtecture都有自己的一个sys call table比如mips的就在
arch/mips/kernel/scall32-o32.S ; arch/mips/kernel/scall64-64.S; arch/mips/kernel/{platform}
等文件中的sys_call_table。 里面可以查到sys_ioctl函数指针的值。至于怎么对应到具体函数,是由
一堆汇编来搞的,看不懂。
.sys_ioctl()函数,位置在fs/ioctl.c
获取文件指针,struct file * filp = fget_light(fd, &fput_needed);
注意这个fd,就是socket()函数生成,由ioctl()调用时传入的值.在我们调用socket()的时候,内核就为该socket
准备好了“文件",并用inode在内核来代表之,以及该文件的句柄fd,这里就是通过fd,找到该"文件"。inode结构
里有个i_mode这个flag,使用来标记文件类型的。如果为socket,则,其值(i_mode & S_IFMT) == S_IFSOCK.
其他的可以参考 include/kernel/stat.h:
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
那么我们在用户层调用socket()的时候,其inode的i_mode的值就置好了(见net/socket.c/)。到这里的时候我们就可以利用之了。
继续看函数调用
.sys_ioctl()->vfs_ioctl()
该函数根据用户层传来的command,如果是下列几个命令:
case FIOCLEX://对文件设置专用标志,通知内核自动关闭打开的文件
case FIONCLEX://与FIOCLEX标志相反,清除专用标志
case FIONBIO://将文件操作设置成阻塞/非阻塞
case FIOASYNC:// 将文件操作设置成同步/异步IO
case FIOQSIZE:// ?
这几个命令直接对inode操作,所以不用到具体的“文件”上获取信息,就直接在这里处理掉了
否则如果是普通文件(S_ISREG(m)为真)则以下命令也可以直接执行了:
case FIBMAP://获取内存map
case FIGETBSZ://获取块大小
case FIONREAD://?
最终其他命令得调用do_ioctl()

.vfs_ioctl()->do_ioctl()
这函数很简单,直接调用filp->f_op->

ioctl(),问题是f_op哪里来的。好,回到开头的socket()系统调用
.socket()->sys_socket()同ioctl->sys_ioctl()步骤基本一样
sys_socket()很简单,创建socket后调用 sock_map_fd()来给socket 文件提供操作函数列表
.sys_socket()->sock_map_fd()
首先fd = get_unused_fd();获取一个未使用中的句柄
然后file *file = get_empty_filp();获取一个可使用的file结构
再就是文件系统的一些信息的赋值。同时把socket和file联系起来:sock->file = file;
然后就是:file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;登场。
在这里就回答了上面f_op是哪里来的问题了。
具体的socket_file_ops如下:
static struct file_operations socket_file_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.aio_read = sock_aio_read,
.aio_write = sock_aio_write,
.poll = sock_poll,
.unlocked_ioctl = sock_ioctl,
.mmap = sock_mmap,
.open = sock_no_open, /* special open code to disallow open via /proc */
.release = sock_close,
.fasync = sock_fasync,
.readv = sock_readv,
.writev = sock_writev,
.sendpage = sock_sendpage
};
我们只需要看sock_ioctl
.sock_ioctl()
对于普通socket的命令,如connect(),listen(),bind()等命令,其不需要涉及到具体设备,就直接调用
socket的oprations里面的ioctl,由sock->ops->ioctl指向,这里的ops是socket特有的,不是文件系统的
那个ioctl,由inet_create()函数指定(见net/ipv4/af_inet.c)这里不谈那个东西,掠过。

对于设备相关的ioctl,我们这里调用dev_ioctl(cmd,argp),命令和参数带进去了。
.sock_ioctl()->dev_ioctl()(见net/core/dev.c,终于到核心部分了)
ifconfig命令所需要的东西基本都在里面了。当然一部分具体信息还是调用的有ifname指定的设备驱动程序所提供的
do_ioctl来report给我们,另一部分就从设备结构信息中获取。

===End of ifconfig===






相关文档
相关文档 最新文档