我现在需要新建一个APP来接收linux内核发送netlink消息reset,并打印消息,下面是一个有类似功能的APP的代码,分别为main函数和服务函数
main:
/**************************************************************************************************/
/* INCLUDE_FILES */
/**************************************************************************************************/
/* libc header */
#include <stdio.h>
#include <unistd.h>
/* syscall header */
/* common header */
#include "fepTypes.h"
#include "fepDefs.h"
/* fep header */
#include "pal/msgq.h"
#include "basic/dev_defs.h"
#include "basic/tpshm.h"
#include "tpDbg/tpdebug.h"
#include "mm/mm.h"
#include "midware/dal.h"
#include "midware/tpConfig.h"
#include "midware/tpData.h"
#include "midware/tpNotify.h"
#include "midware/tpRpc.h"
#include "midware/opFrame.h"
#include "midware/fepPacket.h"
#include "midware/tpState.h"
#include "userPort/up_spec.h"
#include "userPort/up_property.h"
#include "userPort/user_port.h"
#include "common/applError.h"
/* cpn public application header */
#include "common/applErrorCpn.h"
// #include "ippool/errIppool.h"
#include "uilib/preferences/uilibIppool.h"
#include "opIppool.h"
#include "srvcIppool.h"
#include "compshell/compShellMgr.h"
/* module private header*/
/**************************************************************************************************/
/* DEFINES */
/**************************************************************************************************/
#define IPPOOL_USR_NAME_MAX_LEN 10
#define IPPOOL_SUB_NAME "IPPOOL"
/**************************************************************************************************/
/* TYPES */
/**************************************************************************************************/
/**************************************************************************************************/
/* EXTERN_PROTOTYPES */
/**************************************************************************************************/
/**************************************************************************************************/
/* LOCAL_PROTOTYPES */
/**************************************************************************************************/
/**************************************************************************************************/
/* VARIABLES */
/**************************************************************************************************/
char l_ippoolUsr[IPPOOL_USR_NAME_MAX_LEN + 1] = {};
int l_unitNum = 0;
// int (*ippoolFun)();
/**************************************************************************************************/
/* LOCAL_FUNCTIONS */
/**************************************************************************************************/
/*
* 平台阶段初始化/逆初始化函数,该函数对进行平台服务相关的库的工作环境初始化
*/
static int ippool_platform_init(void *param)
{
dal_initarg_t dalInitArgs={};
/* pal init */
// char *l_ippoolUsrTemp = NULL;
// l_unitNum = mmCapacityGetNumber("unitNum");
// l_ippoolUsrTemp = (char *)mmCapacityGetString("ippoolUsr");
// if (l_ippoolUsrTemp != NULL) {
// strncpy(l_ippoolUsr, l_ippoolUsrTemp, IPPOOL_USR_NAME_MAX_LEN);
// }
// DBG_ALZ("l_unitNum:%d, l_ippoolUsr:%s.", l_unitNum, l_ippoolUsr);
// ippoolFun(128);
/* pal message queue init */
// if (GL_OK != pal_msgQ_init())
// {
// return ERR_INIT;
// }
/* Platform component and midware enviroment init */
/* device defination and device specification data init */
PFM_IF_FAIL_RET_VAL(dev_defs_init(1),ERR_INIT);
PFM_IF_FAIL_RET_VAL(dev_defs_mod_init(),ERR_INIT);
PFM_IF_FAIL_RET_VAL(up_spec_mod_init(),ERR_INIT);
PFM_IF_FAIL_RET_VAL(upProptModInit(),ERR_INIT);
PFM_IF_FAIL_RET_VAL(user_port_mod_init(),ERR_INIT);
/* tpConfig enviroment init */
/* tpData enviroment init */
PFM_IF_FAIL_RET_VAL(tpDataInit(TPDATA_DEF_INIT),ERR_INIT);
/* tpDal enviroment init */
dalInitArgs.type = DAL_TYPE_APPL;
PFM_IF_FAIL_RET_VAL(dalInit(&dalInitArgs),ERR_INIT);
/* tpNotify enviroment init */
PFM_IF_FAIL_RET_VAL(tpNotifyInit(),ERR_INIT);
/* tpRpc enviroment init */
PFM_IF_FAIL_RET_VAL(tpRpcInit(),ERR_INIT);
PFM_IF_FAIL_RET_VAL(tpConfig_dispatchInit(),ERR_INIT);
PFM_IF_FAIL_RET_VAL(tpState_channelInit(),ERR_INIT);
return ERR_NO_ERROR;
}
static int ippool_platform_deinit(void *param)
{
return ERR_NO_ERROR;
}
/*
* 应用进程私有业务环境初始化函数
*/
static int ippool_private_init(void *param)
{
//PFM_IF_FAIL_RET_VAL(mm_app_prvt_srvc_init(), ERR_INIT);
return ERR_NO_ERROR;
}
static int ippool_private_deinit(void *param)
{
return ERR_NO_ERROR;
}
/*
* 应用进程提供的外部数据处理接口初始化,主要是面向中间件的回调函数注册
*/
static int ippool_public_init(void *param)
{
/* op layer init: including midware callback registration */
// APPL_IF_ERR_RET(opIppoolInit());
/* public service start: opFrame */
//PFM_IF_FAIL_RET_VAL(opFrameInit(OP_FRAME_STACK_SIZE_DEF),ERR_INIT);
//PFM_IF_FAIL_RET_VAL(opFrameStart(),ERR_INIT);
// GR_PRINT_DEBUG("app type is (%u)", gr_client_get_app_type());
return ERR_NO_ERROR;
}
static int ippool_public_deinit(void *param)
{
return ERR_NO_ERROR;
}
/*
* 主要用于启动业务模块进程的私有业务
*/
static int ippool_appl_init(void *param)
{
mm_app_prvt_srvc_action(IPPOOL_PRVT_SRVC, MM_APP_SRVC_START);
return ERR_NO_ERROR;
}
static int ippool_appl_deinit(void *param)
{
return ERR_NO_ERROR;
}
/*
* 处理模块配置前的准备工作,目前主要用于实现等待堆叠收敛
*/
static int ippool_precfg_init(void *param)
{
return ERR_NO_ERROR;
}
static int ippool_precfg_deinit(void *param)
{
return ERR_NO_ERROR;
}
/*
* 写入模块的默认配置相关的数据
*/
static int ippool_defcfg_init(void *param)
{
return ERR_NO_ERROR;
}
static int ippool_defcfg_deinit(void *param)
{
return ERR_NO_ERROR;
}
/*
* 加载模块的用户配置,私有配置
*/
static int ippool_loadcfg_init(void *param)
{
return ERR_NO_ERROR;
}
static int ippool_loadcfg_deinit(void *param)
{
return ERR_NO_ERROR;
}
/*
* 进入stable状态时/配置加载之后的其他操作初始化
*/
static int ippool_stable_init(void *param)
{
return ERR_NO_ERROR;
}
static int ippool_stable_deinit(void *param)
{
return ERR_NO_ERROR;
}
/**************************************************************************************************/
/* PUBLIC_FUNCTIONS */
/**************************************************************************************************/
static __attribute__((constructor)) int init_ippool()
{
mm_app_init_t initFunc = {0};
mm_app_prvt_srvc_t srvc[] =
{
{
.tid = PAL_THREAD_ERROR,
.func = ippoolSrvc,
.pre_exit_f = ippoolSrvcExit,
.name = "ippool",
.start = MM_APP_SRVC_IDLE,
.stack_size = SRVC_IPPOOL_STACK_SIZE_DEFAULT,
.prio = SRVC_IPPOOL_PRIO_DEFAULT,
.srvc_id = IPPOOL_PRVT_SRVC,
.meta_arg = NULL
}
};
DBG("ippool main start.");
initFunc._init_platform = ippool_platform_init;
initFunc._deinit_platform = ippool_platform_deinit;
initFunc._init_private = ippool_private_init;
initFunc._deinit_private = ippool_private_deinit;
initFunc._init_public = ippool_public_init;
initFunc._deinit_public = ippool_public_deinit;
initFunc._init_application = ippool_appl_init;
initFunc._deinit_application = ippool_appl_deinit;
initFunc._init_preconfig = ippool_precfg_init;
initFunc._deinit_preconfig = ippool_precfg_deinit;
initFunc._init_defconfig = ippool_defcfg_init;
initFunc._deinit_defconfig = ippool_defcfg_deinit;
initFunc._init_loadconfig = ippool_loadcfg_init;
initFunc._deinit_loadconfig = ippool_loadcfg_deinit;
initFunc._init_stable = ippool_stable_init;
initFunc._deinit_stable = ippool_stable_deinit;
shell_init_func_t shell_initfunc = {};
memcpy(&(shell_initfunc.mm_init_table), &initFunc, sizeof(mm_app_init_t));
shell_regfunc(MODULE_IPPOOL_INDEX, shell_initfunc, srvc, mm_app_srvc_size(srvc), IPPOOL_SUB_NAME);
// PFM_IF_FAIL_RET_VAL(mm_app_init(&initFunc, srvc, mm_app_srvc_size(srvc)), -1);
DBG("ippool main loop.");
//mm_app_main_loop();
return 0;
}
服务:
#include <stdio.h>
#include <unistd.h>
#include "fepTypes.h"
#include "fepDefs.h"
#include "pal/msgq.h"
#include "basic/dev_defs.h"
#include "basic/tpshm.h"
#include "tpDbg/tpdebug.h"
#include "mm/mm.h"
#include "midware/tpConfig.h"
#include "midware/tpState.h"
#include "common/applError.h"
#include "srvcIppool.h"
#include "libAppCpn/libIppool.h"
#include "opIppool.h"
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/un.h>
#include <sys/socket.h>
int ippoolSrvc(void *param)
{
int serv_fd, client_fd;
struct sockaddr_un addr;
unsigned int getIp = 0;
serv_fd = socket(AF_UNIX, SOCK_STREAM, 0);
unlink(SOCKET_PATH);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);
if (bind(serv_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
{
DBG_INFO_DEBUG("bind error: %s\n", strerror(errno));
close(serv_fd);
return ERR_INIT;
}
listen(serv_fd, BACKLOG);
while (1)
{
client_fd = accept(serv_fd, NULL, 0);
if (client_fd < 0)
{
DBG_ALZ("accept error\n");
continue;
}
IPPOOL_MSG_REQ req;
int ret = recv(client_fd, &req, sizeof(IPPOOL_MSG_REQ), 0);
if (ret <= 0)
{
close(client_fd);
continue;
}
if (0 == strcmp(req.operation, "getIp"))
{
getIp = opIppoolGetIp(&req);
send(client_fd, &getIp, sizeof(getIp), 0);
}
if (0 == strcmp(req.operation, "freeIp"))
{
opIppoolFreeIp(&req);
}
close(client_fd);
}
close(serv_fd);
return ERR_NO_ERROR;
}
int ippoolSrvcExit(void *param)
{
return ERR_NO_ERROR;
}
服务.h:
#ifndef _SRVC_DPI_H_
#define _SRVC_DPI_H_
#ifdef __cplusplus
extern "C" {
#endif
#define SRVC_IPPOOL_STACK_SIZE_DEFAULT 10240
#define SRVC_IPPOOL_PRIO_DEFAULT PAL_THREAD_PRIO_IGNORE
#define BACKLOG 10
// typedef enum
// {
// IPPOOL_PRVT_SRVC = 0,
// IPPOOL_PRVT_SRVC_END
// }IPPOOL_PRVT_SRVC_E;
int ippoolSrvc(void *param);
int ippoolSrvcExit(void *param);
#ifdef __cplusplus
}
#endif
#endif
这是我内核发送netlink消息相关的代码:
#define NETLINK_GPIO_EVENT 31
struct gpio_netlink_msg{
char button_name[32];
unsigned int event_type;
int value;
unsigned long timestamp;
};
static struct sock *gpio_nl_sk = NULL;
static void send_gpio_netlink_event(const char *name, unsigned int type, int value)
{
struct sk_buff* skb;
struct nlmsghdr *nlh;
struct gpio_netlink_msg *msg;
int size = sizeof(struct gpio_netlink_msg);
int len;
if(!gpio_nl_sk){
BH_ERR("Netlink socket not intialized\n");
return;
}
len = NLMSG_SPACE(size);
skb = alloc_skb(len, GFP_ATOMIC);
if(!skb){
BH_ERR("Failed to allocate netlink skb\n");
return;
}
nlh = (struct nlmsghdr *)skb->data;
nlh->nlmsg_len = NLMSG_LENGTH(size);
nlh->nlmsg_type = 0;
nlh->nlmsg_flags = NLM_F_REQUEST;
nlh->nlmsg_seq = 0;
nlh->nlmsg_pid = 0;
msg = (struct gpio_netlink_msg *)NLMSG_DATA(nlh);
strncpy(msg->button_name, name, sizeof(msg->button_name)-1);
msg->button_name[sizeof(msg->button_name)-1] = '\0';
msg->event_type = type;
msg->value = value;
msg->timestamp = jiffies;
skb_put(skb, NLMSG_SPACE(size));
netlink_broadcast(gpio_nl_sk, skb, 0, 1, GFP_ATOMIC);
BH_DBG("Netlink message send for %s ,value = %d\n", name, value);
}
static int create_netlink_socket(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
struct netlink_kernel_cfg cfg ={
.input = NULL,
.groups = 1,
};
gpio_nl_sk = netlink_kernel_create(&init_net, NETLINK_GPIO_EVENT, &cfg);
#else
gpio_nl_sk = netlink_kernel_create(&init_net, NETLINK_GPIO_EVENT, 1, NULL, NULL, THIS_MODULE);
#endif
if(!gpio_nl_sk){
BH_ERR("Failed to create netlink socket\n");
return -ENOMEM;
}
BH_DBG("Netlink socket created successfully\n");
return 0;
}
static void release_netlink_socket(void)
{
if(gpio_nl_sk){
netlink_kernel_release(gpio_nl_sk);
gpio_nl_sk = NULL;
}
}
static void button_hotplug_event(struct gpio_keys_button_data *data,
unsigned int type, int value)
{
struct bh_priv *priv = &data->bh;
unsigned long seen = jiffies;
int btn;
BH_DBG("event type=%u, code=%u, value=%d\n", type, data->b->code, value);
if ((type != EV_KEY) && (type != EV_SW))
return;
btn = button_get_index(data->b->code);
if (btn < 0)
return;
button_hotplug_create_event(button_map[btn].name, type,
(seen - priv->seen) / HZ, value);
if(data->b->code == KEY_RESTART){
BH_DBG("Reset button event detected, sending netlink message\n");
send_gpio_netlink_event("reset", type, value);
}
priv->seen = seen;
}
struct gpio_keys_button_dev {
int polled;
struct delayed_work work;
struct device *dev;
struct gpio_keys_platform_data *pdata;
struct gpio_keys_button_data data[0];
};
现在我给新建APP创建了三个文件,分别是:mainGpioReset.c,srvcGpioReset.c,srvcGpioReset.h,代码该怎么写?