linux_echo_内核态服务器
来源:互联网 发布:做淘宝运营对数据分析 编辑:程序博客网 时间:2024/06/17 19:33
kserver.h
/* * Copyright(C) 2016 Ruijie Network. All rights reserved. *//* * kserver.c * Original Author: suntianyu@ruijie.com.cn, 2016-8-7 * * echo Kernel server * * History * */ #ifndef _SERVER_H_ #define _SERVER_H_#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/types.h> #include <linux/sched.h> #include <linux/netlink.h> #include <net/sock.h> #include <linux/proc_fs.h> #include <linux/mutex.h>#include <linux/sched.h> #include <linux/kthread.h> #define USER_NETLINK_CMD 25 #define MAXMSGLEN 1024 #define MODULE_NAME "/proc" #define DATA_LEN 30 #define NETLINK_ECHO 31#define KTHREAD_NUM 4#define NORMAL_LEN 512#define MAX_USERS 2#define ERROR -1#define NORMAL_MODE 3#define UPPER_MODE 2#define LOWER_MODE 1#define NATIVE 0#define TABLE_SIZE 3#define PIDTABLE_SIZE 2#define TEN 10#define READ_NOW 1#define TOASCI 32#define MODE_SIZE 4#define UPPER_SIZE 5#define LOWER_SIZE 5#define NORMAL_SIZE 6struct db_data_t { char mode[DATA_LEN + 1]; char characters[DATA_LEN + 1]; char clients[DATA_LEN + 1]; }; struct nksend_msg{ int mode; int pid; char *data; struct nksend_msg * next;};struct queue_t{ struct nksend_msg * head; struct nksend_msg * tail;};static DEFINE_MUTEX(mutex);#endif /* _SERVER_H_ */
kserver.c
/* * Copyright(C) 2016 Ruijie Network. All rights reserved. *//* * kserver.c * Original Author: suntianyu@ruijie.com.cn, 2016-8-7 * * echo Kernel server * * History * */ #include "kserver.h"static struct task_struct *tsk_consumes[KTHREAD_NUM];static struct proc_dir_entry *proc_file; static struct proc_dir_entry *echo_dir ;struct db_data_t proc_data; struct sock *netlink_fd; struct nlmsghdr *nlhdr; struct queue_t queue;char buff[NORMAL_LEN];char echo_database[TABLE_SIZE][DATA_LEN] = {"Global mode: normal ","characters: 0 ","clients: 0 "}; int pid = READ_NOW ;int native_mode = NORMAL_MODE;int characters = NATIVE, clients = NATIVE;int output_config[TABLE_SIZE] = {NATIVE,NATIVE,NORMAL_MODE};int pid_outmode[PIDTABLE_SIZE][MAX_USERS]; /* queue */ int init_queue(void){ queue.tail = (struct nksend_msg *)kmalloc(sizeof(struct nksend_msg), 0); if (queue.tail == NULL ) { return ERROR; } queue.head = queue.tail; queue.tail->next = NULL; return 0;}/* queue */bool is_queue_empty(void){ return queue.head == queue.tail;}/* queue */void queue_insert(struct nksend_msg * pnk_msg){ if (pnk_msg == NULL ) { return; } pnk_msg->next = NULL; queue.head->next = pnk_msg; queue.head = pnk_msg;}/* queue */struct nksend_msg * queue_mv_tail(void){ struct nksend_msg * ret; ret = queue.tail->next; queue.tail->next = queue.tail->next->next; if ( ret == queue.head ) { queue.head = queue.tail; } return ret;}/* queue */void clear_queue(struct queue_t * hq) { struct nksend_msg * p; if ( !is_queue_empty()) { p = hq->tail; while(p != NULL) { hq->tail = hq->tail->next; kfree(p); p = hq->tail; } } hq->head = NULL; hq->tail = NULL; return; } /* pid table */void init_pid_table(int native_mode){ int i; for ( i=0; i < MAX_USERS; i++ ) { pid_outmode[0][i] = 0; } for ( i=0; i < MAX_USERS; i++ ) { pid_outmode[1][i] = native_mode; } }/* pid table */int insert_pid(int pid){ int i; for ( i=0; i < MAX_USERS; i++ ) { if (pid_outmode[0][i] == pid) { return ERROR; } } for ( i=0; i < MAX_USERS; i++ ) { if ( pid_outmode[0][i] == 0 ) { clients++; pid_outmode[0][i] = pid; pid_outmode[1][i] = native_mode; return i; } } if ( clients > MAX_USERS) { clients--; return ERROR; } return ERROR;}/* pid table */int delete_pid(int pid){ int i; for ( i=0; i < MAX_USERS; i++ ) { if ( pid_outmode[0][i] == pid ) { clients--; pid_outmode[1][i] = native_mode; pid_outmode[0][i] = 0; return i; } } return 0;}/* pid table */int find_outmode(int pid){ int i; for ( i=0; i < MAX_USERS; i++ ) { if ( pid_outmode[0][i] == pid ) { return pid_outmode[1][i]; } } return native_mode;}/* pid table */int set_outmode(int pid,int mode){ int i; for ( i=0; i < MAX_USERS; i++ ) { if ( pid_outmode[0][i] == pid ) { pid_outmode[1][i] = mode; } } return 0;} /* string processing */int kstrlen(const char *str){ int len; len = 0; if ( str == NULL ) { return 0; } while ( *str++ ) { len++; } return len;}/* string processing */int atoi(char *str){ int i,value; value = 0; if ( str == NULL ) { return 0; } for ( i = 0; i < DATA_LEN; i++ ) { if ( *str >= '0' && *str <= '9' ) { value *= TEN; value += *str - '0'; } str++; } return value;}/* string processing */void itoa(int n,char *s){ int sign,i; char temp; char *p,*q; if ( s == NULL ) { return; } sign = n; i = 0; p = s; q = s; if (sign < 0) { n = -n; } do { s[i++] = n % TEN + '0'; n = n / TEN; } while (n > 0); if ( sign < 0 ) { s[i++] = '-'; } s[i] = '\0'; /* rev */ while ('\0' != *(++q + 1)) { } while (p < q) { if ( *p != *q ) { temp = *p; *p = *q; *q = temp; } ++p; --q; }}/* input judge */ int judge_input(char *input_buf){ int i,j; char mode[MODE_SIZE] = "mode"; char char_lower[LOWER_SIZE ] = "lower"; char char_upper[UPPER_SIZE] = "upper" ; char char_normal[NORMAL_SIZE] = "normal"; if ( input_buf == NULL ) { return 0; } /* mode */ for ( i = 0; i < MODE_SIZE; i++ ) { if ((*(input_buf + i)) != mode[i]) { return ERROR; } } output_config[1] = atoi(input_buf); /* lower */ for ( i = MODE_SIZE,j=0; i < DATA_LEN; i++ ) { if ( (*(input_buf + i) >= 'a'&&*(input_buf + i) <= 'z') || (*(input_buf + i) >= 'A'&&*(input_buf + i) <= 'Z') ){ if ((*(input_buf + i)) != char_lower[j]) { break; } else { j++; } } if ( j == LOWER_SIZE ) { output_config[0] = READ_NOW ; output_config[2] = LOWER_MODE ; if ( output_config[1] == 0 ) { memcpy(&echo_database[0][13],char_lower,LOWER_SIZE ); echo_database[0][18] = '\0'; } return 1; } } /* upper */ for ( i = MODE_SIZE,j=0; i < DATA_LEN; i++ ) { if ( (*(input_buf + i) >= 'a' && *(input_buf + i) <= 'z') || (*(input_buf + i) >= 'A'&&*(input_buf + i) <= 'Z') ) { if ( (*(input_buf + i)) != char_upper[j] ) { break; } else { j++; } } if ( j == UPPER_SIZE ) { output_config[0] = READ_NOW ; output_config[2] = UPPER_MODE ; if ( output_config[1] == 0 ) { memcpy(&echo_database[0][13],char_upper,UPPER_SIZE); echo_database[0][18] = '\0'; } return 1; } } /* normal */ for ( i = MODE_SIZE,j=0; i < DATA_LEN; i++ ) { if ( (*(input_buf + i) >= 'a'&&*(input_buf + i) <= 'z') || (*(input_buf + i) >= 'A'&&*(input_buf + i) <= 'Z') ) { if ((*(input_buf + i)) != char_normal[j]) { break; } else { j++; } } if (j == NORMAL_SIZE) { output_config[0] = READ_NOW ; output_config[2] = NORMAL_MODE ; if (output_config[1] == 0) { memcpy(&echo_database[0][13],char_normal,NORMAL_SIZE); } return 1; } } return 0;}/* */int connection_check(char *data, char *id, int num){ int i; if ( data == NULL ) { return 0; } if ( id == NULL ) { return 0; } for ( i=0; i < num; i++ ) { if ( *(data + i) != *(id + i) ) { return 0; } } return 1;}/* proc */ static int proc_read_foobar(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; len = 0; if ( characters < TEN ) { echo_database[1][12] = '0' + characters; echo_database[1][13] = ' '; } else { itoa(characters,&echo_database[1][12]); } if ( clients < TEN) { echo_database[2][9] = '0' + clients; echo_database[2][10] = ' '; } else { itoa(clients,&echo_database[2][9]); } mutex_lock(&mutex); len = sprintf(page, "%s\n%s\n%s\n",echo_database[0], echo_database[1], echo_database[2]); mutex_unlock(&mutex); return len; } /* proc */ static int proc_write_foobar(struct file *file, const char *buffer, unsigned long count, void *data) { int len,i; char input_data[DATA_LEN]; memset(input_data,0,DATA_LEN); if ( count > DATA_LEN) { len = DATA_LEN; } else { len = count; } if ( copy_from_user(input_data, buffer, len)) { return -EFAULT; } judge_input(input_data); if ( output_config[0] == READ_NOW ) { output_config[0] = 0; if ( output_config[1] == 0) { native_mode = output_config[2]; for ( i=0; i < MAX_USERS; i++) { pid_outmode[1][i] = native_mode; } } else { set_outmode(output_config[1],output_config[2]); } } return len; } /****************************/ /* netlink */ /**************************/ /* netlink 发送数据给用户空间 */static void netlink_to_user(int dest, void *buf, int len){ struct nlmsghdr *nl; struct sk_buff *skb; int size; size = NLMSG_SPACE(len); skb = alloc_skb(size, GFP_ATOMIC); if ( !skb || !buf) { printk(KERN_ALERT "netlink_to_user skb of buf null!\n"); return; } nl = nlmsg_put(skb, 0, 0, 0,NLMSG_SPACE(len) - sizeof(struct nlmsghdr), 0); if(!nl) { return; } NETLINK_CB(skb).pid = 0; NETLINK_CB(skb).dst_group = 0; memcpy(NLMSG_DATA(nl), buf, len); netlink_unicast(netlink_fd, skb, dest, MSG_DONTWAIT); }/* netlink 回调函数 */static void netlink_recv_msg(struct sk_buff *p__skb){ struct sk_buff *skb; char login[] = "suntianyu"; char logout[] = "quit"; struct nksend_msg * pnk_msg; skb = skb_get(p__skb); if (skb->len >= NLMSG_SPACE(0)) { characters++; nlhdr = nlmsg_hdr(skb); pid = nlhdr->nlmsg_pid; memcpy(buff, NLMSG_DATA(nlhdr), sizeof(buff)); kfree_skb(skb); if (connection_check(buff,login,sizeof(login))) { if (insert_pid(pid) == ERROR) { netlink_to_user(pid, logout, sizeof(logout)); return; } else { netlink_to_user(pid, login, sizeof(login)); } } else if (connection_check(buff,logout,sizeof(logout))) { delete_pid(pid); netlink_to_user(pid, logout, sizeof(logout)); } else { pnk_msg = (struct nksend_msg * )kmalloc(sizeof(struct nksend_msg), 0); if (pnk_msg == NULL) { return; } pnk_msg->data = (char * )kmalloc(kstrlen(buff) + 1, 0); if (pnk_msg->data == NULL) { kfree(pnk_msg); return; } memcpy(pnk_msg->data, buff, kstrlen(buff) + 1); pnk_msg->mode = find_outmode(pid); pnk_msg->pid = pid; pnk_msg->data[kstrlen(buff)] = '\0'; mutex_lock(&mutex); queue_insert(pnk_msg); mutex_unlock(&mutex); } return; } else { /* End of if */ printk("netlink received error!\n"); } return; } /*********************************/ /* kthread线程处理函数 */ /*******************************/ static int kthread_consume(void *data){ bool flag; int k,i; char buf[NORMAL_LEN]; struct nksend_msg * pnk_msg; k = (int)data; do{ flag = 0; mutex_lock(&mutex); if ( !is_queue_empty()) { pnk_msg = queue_mv_tail(); flag = 1; } mutex_unlock(&mutex); if (flag) { msleep_interruptible(200*(kstrlen(pnk_msg->data)-1)); memcpy(buf,pnk_msg->data,kstrlen(pnk_msg->data)); if ( pnk_msg->mode == LOWER_MODE) { for ( i = 0; ((i < NORMAL_LEN) && (buf[i] != '\0')); i++ ) { if ( buf[i] >= 'A' && buf[i] <= 'Z') { buf[i] = buf[i] + TOASCI; } } } else if (pnk_msg->mode == UPPER_MODE){ for ( i = 0; ((i < NORMAL_LEN) && (buf[i] != '\0')); i++ ) { if ( buf[i] >= 'a' && buf[i] <= 'z') { buf[i] = buf[i] - TOASCI; } } } memcpy(pnk_msg->data, buf, kstrlen(pnk_msg->data)); netlink_to_user(pnk_msg->pid,pnk_msg->data,NORMAL_LEN); kfree(pnk_msg->data); kfree(pnk_msg); } } while (!kthread_should_stop()); return 0;}/************************/ /* 初始化 */ /**********************/static int init_kthreads(void){ int i; for ( i=0; i < KTHREAD_NUM; i++) { tsk_consumes[i] = kthread_run(kthread_consume, (void*)i, "kthread_consume%d", i); if (IS_ERR(tsk_consumes[i])) { return ERROR; } } return 0;}/* init proc */int init_proc(void){ echo_dir = proc_mkdir("ruijie", NULL); proc_file = create_proc_entry("echo_db", 0666, echo_dir); if ( !proc_file) { printk(KERN_ERR "can't create /proc/echo_db \n"); return ERROR; } proc_file->data = echo_database; proc_file->read_proc = proc_read_foobar; proc_file->write_proc = proc_write_foobar; return 0;}/* netlink init*/static int __init netlink_init(void){ mutex_init(&mutex); /* init queue */ if ( init_queue() == ERROR ) { printk(KERN_ALERT "Init queue faill!\n"); return ERROR; } /* init pid_table */ init_pid_table(native_mode); /* create proc */ if ( init_proc() == ERROR ) { printk(KERN_ALERT "Init proc faill!\n"); return ERROR; } /* init netlink */ netlink_fd = netlink_kernel_create(&init_net, NETLINK_ECHO, 1, netlink_recv_msg, NULL, THIS_MODULE); if ( netlink_fd == NULL) { printk(KERN_ALERT "Init netlink faill!\n"); return ERROR; } /* create kthread */ if ( init_kthreads() == ERROR ) { printk(KERN_ALERT "Init thread faill!\n"); return ERROR; } printk(KERN_ALERT "Init proc,netlink,pthread,queue, success!\n"); printk("\nRui Jie ECHO Server,Init!!! Author:Sun tian yu\n"); return 0; } /* exit */ static void __exit netlink_exit(void){ int i; /* clear queue */ clear_queue(&queue); /* proc */ remove_proc_entry("echo_db", echo_dir); remove_proc_entry("ruijie", NULL); /* clear kthread */ for ( i=0; i < KTHREAD_NUM; i++) { if (!IS_ERR(tsk_consumes[i])) { kthread_stop(tsk_consumes[i]); } } /* clear netlink */ netlink_kernel_release(netlink_fd); printk(KERN_ALERT "Exit netlink!\n"); } MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("SunTianYu"); module_init(netlink_init); module_exit(netlink_exit);
0 0
- linux_echo_内核态服务器
- linux_echo_用户态服务器
- linux_echo_客户端
- 服务器升级linux内核
- linux查看服务器内核
- web服务器内核优化
- ubuntu服务器升级内核
- linux内核中的服务器模式
- 浅谈PHP内核与服务器
- linux内核文件翻译- RPCSEC_GSS内核RPC服务器支持
- 服务器单纯的升级内核 centos升级内核为3.10
- FreeBSD5.4内核配置文件(服务器专用)
- pppoe内核编译及服务器架设
- 微软推Windows 8服务器内核
- linux 服务器网络有关的内核参数
- tftp服务器完成linux内核下载
- 高负载web服务器内核参数调整
- 服务器常用的内核调优
- Android酷炫开源动框架2015-2016双年榜
- 01-从Java到Golang快速入门
- 常见面试之机器学习算法思想简单梳理
- 分页语句创建索引技巧
- 集合框架_Collections工具类的常见方法讲解
- linux_echo_内核态服务器
- 前端学习day02
- poj 1191 棋盘分割
- What day is that day?(打表找周期)
- 微信小程序开发视频教程
- jQuery ajax - load() 方法 回调函数以及如何得到回调结果中需要的数据值
- DAO模式
- OpenCV Mat与QImage相互转换函数
- JAVA UDP协议编程