沈家弄路700号在哪的:使用sockopt实现内核与用户之间通信

来源:百度文库 编辑:中财网 时间:2024/04/28 08:16:50
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
#include
#include
#include
#include
#include
#include
#define SOCKET_OPS_BASE          128
#define SOCKET_OPS_SET       (SOCKET_OPS_BASE)
#define SOCKET_OPS_GET      (SOCKET_OPS_BASE)
#define SOCKET_OPS_MAX       (SOCKET_OPS_BASE + 1)
#define KMSG          "a message from kernel"
#define KMSG_LEN      sizeof("a message from kernel")
MODULE_LICENSE("GPL");
static int recv_msg(struct sock *sk, int cmd, void *user, unsigned int len)
{
int ret = 0;
printk(KERN_INFO "sockopt: recv_msg()\n");
/*
switch(cmd)
{
case IMP1_SET:
{
char umsg[64];
memset(umsg, 0, sizeof(char)*64);
copy_from_user(umsg, user, sizeof(char)*64);
printk("umsg: %s", umsg);
}
break;
}
*/
if (cmd == SOCKET_OPS_SET)
{
char umsg[64];
int len = sizeof(char)*64;
memset(umsg, 0, len);
ret = copy_from_user(umsg, user, len);
printk("recv_msg: umsg = %s. ret = %d\n", umsg, ret);
}
return 0;
}
static int send_msg(struct sock *sk, int cmd, void *user, int *len)
{
int ret = 0;
printk(KERN_INFO "sockopt: send_msg()\n");
if (cmd == SOCKET_OPS_GET)
{
ret = copy_to_user(user, KMSG, KMSG_LEN);
printk("send_msg: umsg = %s. ret = %d. success\n", KMSG, ret);
}
return 0;
}
static struct nf_sockopt_ops test_sockops =
{
.pf = PF_INET,
.set_optmin = SOCKET_OPS_SET,
.set_optmax = SOCKET_OPS_MAX,
.set = recv_msg,
.get_optmin = SOCKET_OPS_GET,
.get_optmax = SOCKET_OPS_MAX,
.get = send_msg,
};
static int __init init_sockopt(void)
{
printk(KERN_INFO "sockopt: init_sockopt()\n");
return nf_register_sockopt(&test_sockops);
}
static void __exit fini_sockopt(void)
{
printk(KERN_INFO "sockopt: fini_sockopt()\n");
nf_unregister_sockopt(&test_sockops);
}
module_init(init_sockopt);
module_exit(fini_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
#include
#include
#include
#include
#include
#define SOCKET_OPS_BASE      128
#define SOCKET_OPS_SET       (SOCKET_OPS_BASE)
#define SOCKET_OPS_GET      (SOCKET_OPS_BASE)
#define SOCKET_OPS_MAX       (SOCKET_OPS_BASE + 1)
#define UMSG      "a message from userspace"
#define UMSG_LEN  sizeof("a message from userspace")
char kmsg[64];
int main()
{
int sockfd;
int len;
int ret;
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if(sockfd < 0)
{
printf("can not create a socket\n");
return -1;
}
/*call function recv_msg()*/
ret = setsockopt(sockfd, IPPROTO_IP, SOCKET_OPS_SET, UMSG, UMSG_LEN);
printf("setsockopt: ret = %d. msg = %s\n", ret, UMSG);
len = sizeof(char)*64;
/*call function send_msg()*/
ret = getsockopt(sockfd, IPPROTO_IP, SOCKET_OPS_GET, kmsg, &len);
printf("getsockopt: ret = %d. msg = %s\n", ret, kmsg);
if (ret != 0)
{
printf("getsockopt error: errno = %d, errstr = %s\n", errno, strerror(errno));
}
close(sockfd);
return 0;
}
pc机与单片机之间如何实现串口通信,用汇编语言实现? motoe685不能实现与电脑通信。 如何实现单片机与PC机通信 网络通信端口与用户的关系 怎么样用VC++实现计算机之间的通信? 如何实现两台主机之间的通信 UPD协议编程实现单片机和客户机之间的通信 UPD协议编程实现单片机和客户机之间的通信 是不是QQ邮箱只限QQ用户之间的通信啊!!! 怎样使用matlab实现OFDM通信系统的仿真 极点五笔输入法如何实现不同用户之间的共享? win2003如何在不同用户之间实现隐藏分区 中国移动通信计费与绿色环保之间的关系? 射频卡与读写器之间怎样进行通信? 请推荐些PC与手机之间的通信软件 我有一款夏新D86的手机,但我不会使用它与电脑之间进行通信,请教具体的步骤,谢谢! 在网络营销活动中,为实现营销信息的发布、传递、与用户之间的交互等需借助哪些网络营销常用工具? 在网络营销活动中,为实现营销信息的发布、传递、与用户之间的交互等需借助哪些网络营销常用工具? 只用一根网线如何实现两台计算机之间的通信和共享 铁路上半自动闭塞机之间的通信和信息传递是通过什么方式实现的? 用VB 编写的聊天程序,怎样实现多个用户进行通信 我有一个用VB 编写的聊天程序,怎样实现多个用户进行通信 在OSI中,为网络用户之间的通信提供专用程序的层次是 类之间如何通信????