分类: LINUX
2010-07-27 23:49:41
1. Linux下的sockopt
Linux提供了多种通信方式来实现内核和用户之间的数据通信,基于 socket的sockopt是最常用也比较简单易用的一种方式。它的本质和ioctl()很相似,只是ioctl()需要创建新的设备文件,而 sockopt只需要创建一个socket套接字便可以使用户与内核进行通信。
这里分别从内核和用户两方面来介绍sockopt的使用。
2. 内核中使用sockopt
在内核中,Netfilter提供了struct nf_sockopt_ops来将sockopt的操作定义为一个节点来加入链表中。同时提供了注册/解注册函数来使用sockopt。
数据结构和函数
sockopt操作结构体 struct nf_sockopt_ops { struct list_head list; int pf; /* Non-inclusive ranges: use 0/0/NULL to never get called. */ int set_optmin; int set_optmax; int (*set)(struct sock *sk, int optval, void __user *user, unsigned int len); int (*compat_set)(struct sock *sk, int optval, void __user *user, unsigned int len); int get_optmin; int get_optmax; int (*get)(struct sock *sk, int optval, void __user *user, int *len); int (*compat_get)(struct sock *sk, int optval, void __user *user, int *len); /* Number of users inside set() or get(). */ unsigned int use; struct task_struct *cleanup_task; }; 注册和解注册函数 int nf_register_sockopt(struct nf_sockopt_ops *reg) void nf_unregister_sockopt(struct nf_sockopt_ops *reg) 用户数据读写函数 int copy_from_user(void *to, const void __user *from, int n) int copy_to_user(void __user *to, const void *from, int n) |
内核模块代码:
sockopt_srv.c
#include #define SOCKET_OPS_BASE 128 #define KMSG "a message from kernel" MODULE_LICENSE("GPL"); static int recv_msg(struct sock *sk, int cmd, void *user, unsigned int len) static int send_msg(struct sock *sk, int cmd, void *user, int *len) static struct nf_sockopt_ops test_sockops = static int __init init_sockopt(void) static void __exit fini_sockopt(void) module_init(init_sockopt);
|
3. 用户使用sockopt
Linux同样提供了一组用户接口来读写sockopt
#include #include int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); |
在用户进程中,我们可以创建一个socket,然后通过socket来调用getsockopt/setsockopt来和内核空间通信。
用户代码
sockopt_clt.c
#include #define SOCKET_OPS_BASE 128 #define UMSG "a message from userspace" char kmsg[64]; int main() sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); /*call function recv_msg()*/ /*call function send_msg()*/ close(sockfd); |