netlinksocket(linux内核模块与用户态之间通信实例)

阅读: 评论:0

netlinksocket(linux内核模块与⽤户态之间通信实例)
本⽂通过⼀个编程实例来更深⼊地了解netlink。
1.1        实现内容
1.          功能
Ø  实现⼀个并发的echo服务器程序,它(接收端)将接收到字符串进⾏转换处理后,返回给发送端;允许有多个发送端同时存在;
Ø  字符串的处理包括:直接返回、全部转换为⼤写、全部转换为⼩写;处理⽅式应可以配置,配置⽅式
包括全局(缺省)及每“发送-接收对(xmit/recv peer)”的。配置转换时,不应该影响正在处理的字符串;
Ø  为模拟处理过程的延时,接收端中每个字符转换添加200ms的延迟;
Ø  接收端中需统计其处理字符的数量,并且给外部提供命令形式的查询⼿段;
Ø  具备必要的例外处理,如内存不⾜等、client未关闭链接即意外退出等;
1.2        验收成果
1.        程序结构(应⽤专业⽅向)
Ø  以有链接的client-server⽅式实现echo程序
Ø  存在多个client,client与server在同⼀个系统中,它们之间采⽤domain socket或netlink socket相连;client之间没有关联
Ø  client是⼀个程序的多个实例,⽽server只允许运⾏⼀个实例
2.        程序结构(内核专业⽅向)
Ø  内核模块作为接收端(服务器),⽽发送端(客户端)是⽤户空间的应⽤程序;
Ø  内核模块可动态加载与卸载
Ø  驱动相关组:
·          创建虚拟字符型设备,⽤于接受来⾃客户端的字符
·          使⽤ioctl控制接⼝来配置echo处理⽅式,ioctl的cmd⾃定义;
·          并发使⽤驱动的多实例来模拟;
Ø  ⾮驱动相关组:
·          创建内核线程,作为内核中的server,⽤于,通信可采⽤netlink socket或其它可⽤的⽅式;
·          使⽤netlink接⼝来配置echo处理转换⽅式;
⽤户态netlink socket源码
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <linux/netlink.h>
#include <signal.h>
#define NETLINK_TEST    17
#define MSG_LEN        125
#define BUF_LEN        125
#define TIME            210
int skfd;
struct sockaddr_nl local;
struct sockaddr_nl dest;
struct nlmsghdr *message;
struct msg_to_kernel
{
struct nlmsghdr hdr;
char data[MSG_LEN];
};
struct u_packet_info
{
struct nlmsghdr hdr;
char msg[MSG_LEN];
};
static void sig_pipe(int sign)kps
{
printf("Catch a SIGPIPE signal\n");
close(skfd);
kill(local.nl_pid,SIGUSR1);
exit(-1);
}
int init_netlink(void)
{模块化建筑技术
//char *send_data = "aaaaaaaaaaaaBBBBBBBBBBBBBBBBBBaaaaaaaaaaaaaaaaBBBBBBBBBBBB11111112222";    char send_data[BUF_LEN];
message = (struct nlmsghdr *)malloc(1);
skfd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
if(skfd < 0){
printf("can not create a netlink socket\n");
return -1;
}
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_pid = getpid();
local.nl_groups = 0;
if(bind(skfd, (struct sockaddr *)&local, sizeof(local)) != 0){
printf("bind() error\n");
return -1;倒写体
}
memset(&dest, 0, sizeof(dest));
dest.nl_family = AF_NETLINK;
dest.nl_pid = 0;
dest.nl_groups = 0;
memset(message, '\0', sizeof(struct nlmsghdr));
message->nlmsg_len = NLMSG_SPACE(MSG_LEN);
message->nlmsg_flags = 0;
message->nlmsg_type = 0;
message->nlmsg_seq = 0;
message->nlmsg_pid = local.nl_pid;
while(1) {
printf("input  the  data: ");
fgets(send_data, MSG_LEN, stdin);
if(0 == (strlen(send_data)-1))
continue;
else
break;
}
memcpy(NLMSG_DATA(message), send_data, strlen(send_data)-1);    printf("send  to  kernel: %s,  send_id: %d  send_len: %d\n", \
(char *)NLMSG_DATA(message),local.nl_pid, strlen(send_data)-1);    return 0;
}
/**
* NAME: ngsa_test_init
*
* DESCRIPTION:
*      ngsa test model 初始化
* @*psdhdr
贵州师范学院学报* @*addr
* @size
*
* RETURN:
*/
int main(int argc, char* argv[])
{
int ret,len;
socklen_t destlen = sizeof(struct sockaddr_nl);
struct u_packet_info info;
fd_set fd_sets;
struct timeval select_time;
signal(SIGINT, sig_pipe);
signal(SIGINT, sig_pipe);
ret = init_netlink();
if(ret<0) {
close(skfd);
perror("netlink failure!");
exit(-1);
}
FD_ZERO( &fd_sets );
FD_SET( skfd, &fd_sets);
len = sendto(skfd, message, message->nlmsg_len, 0,(struct sockaddr *)&dest, sizeof(dest));
if(!len){
perror("send pid:");
exit(-1);
}
select_time.tv_sec = TIME;
select_time.tv_usec = 0;
ret = select(skfd+1,&fd_sets,NULL,NULL,&select_time);
if(ret > 0){
/* 接受内核态确认信息 */
len = recvfrom(skfd, &info, sizeof(struct u_packet_info),0, (struct sockaddr*)&dest, &destlen);                printf("recv from kernel: %s,  recv_len: %d\n",(char *)info.msg, strlen(info.msg));
}else if(ret < 0) {
perror("\n error! \n");
exit(-1);
}else {
printf("\n kernel server disconncet! \n");
kill(local.nl_pid, SIGUSR1);
}
/* 内核和⽤户关闭通信 */
close(skfd);
return 0;
}
>>>>>>>>>>>>>>### linux内核源码(module.c)
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/cdev.h>
#define MEMDEV_MAJOR    255  /* 预设的mem的主设备号 */
#define MEMDEV_NR_DEVS  1    /* 设备数 */
#define MEMDEV_SIZE    1024  /* 分配内存的⼤⼩ */
#define NETLINK_TEST    17
#define UP_TO_LOW      0
#define LOW_TO_UP      1
#define LOW_TO_UP      1
#define MAX_PID_COUNT  100
#define MSG_LEN        125
#ifndef SLEEP_MILLI_SEC
#define SLEEP_MILLI_SEC(nMillisec) \
do { \
long timeout = (nMillisec) * HZ /1000; \
while (timeout > 0) { \
timeout = schedule_timeout(timeout); \
} \
}while(0);
#endif
static int echo_major = MEMDEV_MAJOR;
module_param(echo_major, int, S_IRUGO);
struct echo_dev *echo_devp;                  /*设备结构体指针*/
struct cdev cdev;
char *echo_dev = "echodev";
static struct sock *netlinkfd = NULL;
static struct task_struct *task_test[MAX_PID_COUNT];
static int pid_index = 0;
static int char_num = 0;
static int char_cnvt_flag = 0;
/* mem设备描述结构体 */
struct echo_dev
{
char *data;          /* 分配到的内存的起始地址 */
中国司法独立unsigned long size;  /* 内存的⼤⼩ */
tiammao};
struct{
__u32 pid;
}user_process;
/* netlink */
struct echo_netlink
{
__u32 pid;            /* netlink pid */
char  buf[MSG_LEN];  /* data */
int  length;        /* buf len  */
};
struct echo_netlink client_netlink[MAX_PID_COUNT];
static int echo_open(struct inode *inode, struct file *filp);
static ssize_t echo_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos); static long echo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
static const struct file_operations echo_fops =
{
.owner = THIS_MODULE,
.open = echo_open,
.read = echo_read,

本文发布于:2023-06-27 15:15:49,感谢您对本站的认可!

本文链接:https://patent.en369.cn/xueshu/137327.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:处理   内核   转换   字符   接收端   实例   发送
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 369专利查询检索平台 豫ICP备2021025688号-20 网站地图