- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试从 LKM 向用户空间发送/接收结构(反之亦然),基于此示例 http://www.electronicsfaq.com/2014/02/generic-netlink-sockets-example-code.html .
我向内核发送一个结构。它接收结构 ok,处理信息,并将结构发送回用户空间。但是,如果该结构有 2 个字段,我可以发送和接收,但是当我再添加一个字段时,我会收到一个空结构。自 2 天前以来,我已经探索了一些变体,但一直没有成功。我很困惑,我不确定问题出在哪里?这是代码:
nl_user.c:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <poll.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <signal.h>
#include "global.h"
#include <linux/genetlink.h>
#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
#define NLA_DATA(na) ((void *)((void*)(na) + NLA_HDRLEN))
//Variables used for netlink
int nl_fd; //netlink socket's file descriptor
struct sockaddr_nl nl_address; //netlink socket address
int nl_family_id;
int nl_rxtx_length; //Number of bytes sent or received via send() or recv()
struct nlattr *nl_na; //pointer to netlink attributes structure within the payload
Response p;
struct {
struct nlmsghdr n;
struct genlmsghdr g;
char buf[256];
} nl_request_msg, nl_response_msg;
int main(void) {
struct {
struct nlmsghdr n;
struct genlmsghdr g;
Response buf;
} my_nl_request_msg, my_nl_response_msg;
//Step 1: Open the socket. Note that protocol = NETLINK_GENERIC
nl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
if (nl_fd < 0) {
perror("socket()");
return -1;
}
//Step 2: Bind the socket.
memset(&nl_address, 0, sizeof(nl_address));
nl_address.nl_family = AF_NETLINK;
nl_address.nl_groups = 0;
if (bind(nl_fd, (struct sockaddr *) &nl_address, sizeof(nl_address)) < 0) {
perror("bind()");
close(nl_fd);
return -1;
}
//Step 3. Resolve the family ID corresponding to the string "CONTROL_EXMPL"
//Populate the netlink header
nl_request_msg.n.nlmsg_type = GENL_ID_CTRL;
nl_request_msg.n.nlmsg_flags = NLM_F_REQUEST;
nl_request_msg.n.nlmsg_seq = 0;
nl_request_msg.n.nlmsg_pid = getpid();
nl_request_msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
//Populate the payload's "family header" : which in our case is genlmsghdr
nl_request_msg.g.cmd = CTRL_CMD_GETFAMILY;
nl_request_msg.g.version = 0x1;
//Populate the payload's "netlink attributes"
nl_na = (struct nlattr *) GENLMSG_DATA(&nl_request_msg);
nl_na->nla_type = CTRL_ATTR_FAMILY_NAME;
nl_na->nla_len = strlen("CONTROL_EXMPL") + 1 + NLA_HDRLEN;
strcpy(NLA_DATA(nl_na), "CONTROL_EXMPL");
nl_request_msg.n.nlmsg_len += NLMSG_ALIGN(nl_na->nla_len);
memset(&nl_address, 0, sizeof(nl_address));
nl_address.nl_family = AF_NETLINK;
//Send the family ID request message to the netlink controller
nl_rxtx_length = sendto(nl_fd, (char *) &nl_request_msg, nl_request_msg.n.nlmsg_len,
0, (struct sockaddr *) &nl_address, sizeof(nl_address));
if (nl_rxtx_length != nl_request_msg.n.nlmsg_len) {
perror("sendto()");
close(nl_fd);
return -1;
}
//Wait for the response message
nl_rxtx_length = recv(nl_fd, &nl_response_msg, sizeof(nl_response_msg), 0);
if (nl_rxtx_length < 0) {
perror("recv()");
return -1;
}
//Validate response message
if (!NLMSG_OK((&nl_response_msg.n), nl_rxtx_length)) {
fprintf(stderr, "family ID request : invalid message\n");
return -1;
}
if (nl_response_msg.n.nlmsg_type == NLMSG_ERROR) { //error
fprintf(stderr, "family ID request : receive error\n");
return -1;
}
//Extract family ID
nl_na = (struct nlattr *) GENLMSG_DATA(&nl_response_msg);
nl_na = (struct nlattr *) ((char *) nl_na + NLA_ALIGN(nl_na->nla_len));
if (nl_na->nla_type == CTRL_ATTR_FAMILY_ID) {
nl_family_id = *(__u16 *) NLA_DATA(nl_na);
}
//Step 4. Send own custom message
memset(&my_nl_request_msg, 0, sizeof(my_nl_request_msg));
memset(&my_nl_response_msg, 0, sizeof(my_nl_response_msg));
my_nl_request_msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
my_nl_request_msg.n.nlmsg_type = nl_family_id;
my_nl_request_msg.n.nlmsg_flags = NLM_F_REQUEST;
my_nl_request_msg.n.nlmsg_seq = 60;
my_nl_request_msg.n.nlmsg_pid = getpid();
my_nl_request_msg.g.cmd = 1; //corresponds to DOC_EXMPL_C_ECHO;
nl_na = (struct nlattr *) GENLMSG_DATA(&my_nl_request_msg);
nl_na->nla_type = 2; // corresponds to DOC_EXMPL_A_MSG
//nl_na->nla_len = sizeof(MESSAGE_TO_KERNEL)+NLA_HDRLEN; //Message length
//memcpy(NLA_DATA(nl_na), MESSAGE_TO_KERNEL, sizeof(MESSAGE_TO_KERNEL));
p.dataSize = 32;
nl_na->nla_len = sizeof(p)+NLA_HDRLEN; //Message length
memcpy(NLA_DATA(nl_na), &p, sizeof(p));
my_nl_request_msg.n.nlmsg_len += NLMSG_ALIGN(nl_na->nla_len);
memset(&nl_address, 0, sizeof(nl_address));
nl_address.nl_family = AF_NETLINK;
//Send the custom message
nl_rxtx_length = sendto(nl_fd, &my_nl_request_msg,my_nl_request_msg.n.nlmsg_len, 0, (struct sockaddr *) &nl_address, sizeof(nl_address));
if (nl_rxtx_length != my_nl_request_msg.n.nlmsg_len) {
perror("sendto()");
close(nl_fd);
return -1;
}
printf("Sent to kernel: %d\n",p.dataSize);
//Receive reply from kernel
nl_rxtx_length = recv(nl_fd, &my_nl_response_msg, sizeof(my_nl_response_msg), 0);
if (nl_rxtx_length < 0) {
perror("recv()");
return -1;
}
//Validate response message
if (my_nl_response_msg.n.nlmsg_type == NLMSG_ERROR) { //Error
printf("Error while receiving reply from kernel: NACK Received\n");
close(nl_fd);
return -1;
}
if (nl_rxtx_length < 0) {
printf("Error while receiving reply from kernel\n");
close(nl_fd);
return -1;
}
if (!NLMSG_OK((&my_nl_response_msg.n), nl_rxtx_length)) {
printf("Error while receiving reply from kernel: Invalid Message\n");
close(nl_fd);
return -1;
}
//Parse the reply message
nl_rxtx_length = GENLMSG_PAYLOAD(&my_nl_response_msg.n);
nl_na = (struct nlattr *) GENLMSG_DATA(&my_nl_response_msg);
Response *r = (Response *)NLA_DATA(nl_na);
printf("Kernel replied: %d\n",r->dataSize);
//Step 5. Close the socket and quit
close(nl_fd);
return 0;
nl_kernel.c:
#include "global.h"
#include <net/genetlink.h>
#include <linux/module.h>
#include <linux/kernel.h>
/* attributes (variables):
* the index in this enum is used as a reference for the type,
* userspace application has to indicate the corresponding type
* the policy is used for security considerations
*/
enum {
DOC_EXMPL_A_UNSPEC,
DOC_EXMPL_A_MSG,
DOC_EXMPL_A_MSG2,
__DOC_EXMPL_A_MAX,
};
#define DOC_EXMPL_A_MAX (__DOC_EXMPL_A_MAX - 1)
static struct nla_policy doc_exmpl_genl_policy[DOC_EXMPL_A_MAX + 1] = {
[DOC_EXMPL_A_MSG] = { .type = NLA_NUL_STRING },
[DOC_EXMPL_A_MSG2] = { .type = NLA_UNSPEC, .len = sizeof(Response) },
};
#define VERSION_NR 1
//family definition
static struct genl_family doc_exmpl_gnl_family = {
.id = GENL_ID_GENERATE, //Genetlink should generate an id
.hdrsize = 0,
.name = "CONTROL_EXMPL",
.version = VERSION_NR, //Version number
.maxattr = DOC_EXMPL_A_MAX,
};
/* commands: enumeration of all commands (functions),
* used by userspace application to identify command to be executed
*/
enum {
DOC_EXMPL_C_UNSPEC,
DOC_EXMPL_C_ECHO,
__DOC_EXMPL_C_MAX,
};
#define DOC_EXMPL_C_MAX (__DOC_EXMPL_C_MAX - 1)
//An echo command, receives a message, prints it and sends another message back
int doc_exmpl_echo(struct sk_buff *skb_2, struct genl_info *info) {
struct nlattr *na;
struct sk_buff *skb;
int rc;
void *msg_head;
char * mydata;
Response *req;
if (info == NULL) {
goto out;
}
if (info->attrs[DOC_EXMPL_A_MSG]) {
na = info->attrs[DOC_EXMPL_A_MSG];
mydata = (char *)nla_data(na);
//req = (Response *)nla_data(na);
if (req == NULL) {
printk("error while receiving data\n");
} else {
//printk("received: %d\n", req->dataSize);
printk("received: %s\n", mydata);
}
}
else if(info->attrs[DOC_EXMPL_A_MSG2]){
na = info->attrs[DOC_EXMPL_A_MSG2];
req = (Response *)nla_data(na);
if (req == NULL) {
printk("error while receiving data\n");
} else {
printk("received2: %d\n", req->dataSize);
}
}else {
printk("no info->attrs %i - %i \n", DOC_EXMPL_A_MSG, DOC_EXMPL_A_MSG2);
}
//Send a message back
//Allocate some memory, since the size is not yet known use NLMSG_GOODSIZE
skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL) {
goto out;
}
//Create the message headers
/* arguments of genlmsg_put:
struct sk_buff *,
int (sending) pid,
int sequence number,
struct genl_family *,
int flags,
u8 command index (why do we need this?)
*/
msg_head = genlmsg_put(skb, 0, info->snd_seq+1, &doc_exmpl_gnl_family, 0, DOC_EXMPL_C_ECHO);
if (msg_head == NULL) {
rc = -ENOMEM;
goto out;
}
req->dataSize *= 10;
printk("req %d\n", req->dataSize);
//Add a DOC_EXMPL_A_MSG attribute (actual value to be sent)
rc = nla_put(skb, DOC_EXMPL_A_MSG2, sizeof(req),req);
if (rc != 0) {
goto out;
}
//Finalize the message
genlmsg_end(skb, msg_head);
//Send the message back
rc = genlmsg_unicast(genl_info_net(info), skb,info->snd_pid );
if (rc != 0) {
goto out;
}
return 0;
out:
printk("An error occured in doc_exmpl_echo:\n");
return 0;
}
//Commands: mapping between the command enumeration and the actual function
struct genl_ops doc_exmpl_gnl_ops_echo = {
.cmd = DOC_EXMPL_C_ECHO,
.flags = 0,
.policy = doc_exmpl_genl_policy,
.doit = doc_exmpl_echo,
.dumpit = NULL,
};
static int __init gnKernel_init(void) {
int rc;
printk("Generic Netlink Example Module inserted.\n");
//Register the new family
rc = genl_register_family(&doc_exmpl_gnl_family);
if (rc != 0) {
goto failure;
}
//Register functions (commands) of the new family
rc = genl_register_ops(&doc_exmpl_gnl_family, &doc_exmpl_gnl_ops_echo);
if (rc != 0) {
printk("Register ops: %i\n",rc);
genl_unregister_family(&doc_exmpl_gnl_family);
goto failure;
}
return 0;
failure:
printk("An error occured while inserting the generic netlink example module\n");
return -1;
}
static void __exit gnKernel_exit(void) {
int ret;
printk("Generic Netlink Example Module unloaded.\n");
//Unregister the functions
ret = genl_unregister_ops(&doc_exmpl_gnl_family, &doc_exmpl_gnl_ops_echo);
if(ret != 0) {
printk("Unregister ops: %i\n",ret);
return;
}
//Unregister the family
ret = genl_unregister_family(&doc_exmpl_gnl_family);
if(ret !=0) {
printk("Unregister family %i\n",ret);
}
}
module_init(gnKernel_init);
module_exit(gnKernel_exit);
MODULE_LICENSE("GPL");
global.h
#ifndef __GLOBAL_H
#define __GLOBAL_H
typedef struct _Response Response;
struct _Response
{
//int index;
int dataSize; /* ammount of data in bytes of the response */
char data[4096];
};
#endif
注意:我在 Oracle VB 中使用的是 Debian 2.6.32-5(这是必需的)。
最佳答案
内核部分的这一行是主要问题。 Sizeof 指针将为 8(在 64 位机器上)或 4。您只发送前几个字节。
rc = nla_put(skb, DOC_EXMPL_A_MSG2, sizeof(req),req);
应该是“sizeof(*req)”。我试过了,但仍然存在数据偏移几个字节的问题......我猜其中一些宏没有按照你认为的那样做。
下面是我刚才做的一个例子,我把它改成了像你这样的结构,它按预期工作。在我看来,这段代码更加清晰。
netlinkKernel.h
#include "global.h"
#include <linux/module.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#define NETLINK_USER 31
struct sock *nl_sk = NULL;
static void hello_nl_recv_msg(struct sk_buff *skb) {
struct nlmsghdr *nlh;
int pid;
struct sk_buff *skb_out;
int msg_size;
int res;
Response *req;
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
msg_size= sizeof(Response);
nlh=(struct nlmsghdr*)skb->data;
req = (Response*)NLMSG_DATA(nlh);
printk("Recieved from Userspace:\n");
printk("index %d\n", req->index);
printk("dataSize %d\n", req->dataSize);
printk("data: %s\n", req->data);
printk("test2 %d\n", req->test2);
printk("test3 %d\n", req->test3);
printk("test4 %d\n", req->test4);
pid = nlh->nlmsg_pid; /*pid of sending process */
skb_out = nlmsg_new(msg_size,0);
if(!skb_out)
{
printk(KERN_ERR "Failed to allocate new skb\n");
return;
}
nlh=nlmsg_put(skb_out,0,0,NLMSG_DONE,msg_size,0);
NETLINK_CB(skb_out).dst_group = 0; /* not in mcast group */
req->index *= 100;
req->dataSize *= 100;
strcpy(req->data , "Data from Kernel");
req->test2 *= 100;
req->test3 *= 100;
req->test4 *= 100;
printk("Sending to Userspace:\n");
printk("index %d\n", req->index);
printk("dataSize %d\n", req->dataSize);
printk("data: %s\n", req->data);
printk("test2 %d\n", req->test2);
printk("test3 %d\n", req->test3);
printk("test4 %d\n", req->test4);
memcpy(NLMSG_DATA(nlh), req, sizeof(Response));
res=nlmsg_unicast(nl_sk,skb_out,pid);
if(res<0)
printk(KERN_INFO "Error while sending bak to user\n");
}
static int __init hello_init(void) {
printk("Entering: %s\n",__FUNCTION__);
// This is for 3.6 kernels and above.
struct netlink_kernel_cfg cfg = {
.input = hello_nl_recv_msg,
};
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
//nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg,NULL,THIS_MODULE);
if(!nl_sk)
{
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
static void __exit hello_exit(void) {
printk(KERN_INFO "exiting hello module\n");
netlink_kernel_release(nl_sk);
}
module_init(hello_init); module_exit(hello_exit);
MODULE_LICENSE("GPL");
netlinkUser.c
#include "global.h"
#include <sys/socket.h>
#include <linux/netlink.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define NETLINK_USER 31
#define MAX_PAYLOAD 8192 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;
Response p;
Response *req;
int main()
{
sock_fd=socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if(sock_fd<0)
return -1;
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_LENGTH(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
p.index = 1;
p.dataSize = 2;
strcpy(p.data , "Data from User");
p.test2 = 3;
p.test3 = 4;
p.test4 = 5;
printf("Sending to Kernel:\n");
printf("index %d\n", p.index);
printf("dataSize %d\n", p.dataSize);
printf("data: %s\n", p.data);
printf("test2 %d\n", p.test2);
printf("test3 %d\n", p.test3);
printf("test4 %d\n", p.test4);
memcpy(NLMSG_DATA(nlh), (void *)&p, sizeof(Response));
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Sending message to kernel\n");
sendmsg(sock_fd,&msg,0);
printf("Waiting for message from kernel\n");
/* Read message from kernel */
recvmsg(sock_fd, &msg, 0);
req = (Response*)NLMSG_DATA(nlh);
printf("Recieved from Kernel:\n");
printf("index %d\n", req->index);
printf("dataSize %d\n", req->dataSize);
printf("data: %s\n", req->data);
printf("test2 %d\n", req->test2);
printf("test3 %d\n", req->test3);
printf("test4 %d\n", req->test4);
close(sock_fd);
}
全局.h
#ifndef __GLOBAL_H
#define __GLOBAL_H
typedef struct _Response Response;
struct _Response
{
int index;
int dataSize; /* ammount of data in bytes of the response */
char data[4096];
int test2;
int test3;
int test4;
};
#endif
如果由于某种原因这对您不起作用,请告诉我。
关于c - 通过通用网络链接从内核到用户空间接收具有 2 个以上字段的结构时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26440963/
运行 Tomcat 失败并出现 java.lang.OutOfMemoryError - 与缺少 PermGen 空间相关的错误。 我最近将 Tomcat 更改为以自己的用户(而非 root)运行。
我们有一个表,其中包含数百万行,其中包含 PostGIS 几何图形。我们要执行的查询是:落在边界几何内的最新条目是什么?这个查询的问题是我们经常会有大量的项目匹配边界框(半径大约为 5 公里),然后
我有一个Elasticsearch设置,它将允许用户搜索通配符作为索引。 array:3 [ "index" => "users" "type" => "user" "body" => arra
我创建了一个表,其中每行包含两个按钮,并且两个按钮连接在一起,我想将两个按钮分开。我用过 不起作用,css 也是,这是他们的另一种方式。 我有另一个问题,因为我不想在表格边框内显示操作按钮,而是在靠近
我试图在 jQuery Mobile 中的两个按钮之间留出空白。现实中的布局是这样的: Button 1 Button 2 (Hidden w/ display: none)
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
您好,我对图表应用程序还很陌生。现在我为我的应用程序创建了条形图。当我运行 create bar chart as separate project 时,输出如下所示。 然后当我将条形图与我的应用程序
我在使用 H2 和 GeoDB(内存中,junit)时遇到问题。 另外,使用 Hibernate 5(每个包的最新版本,包括 hibernate-spatial)和 Spring 4。 通过 id 实
我想画一张澳大利亚的 map ,并将每个城市表示为一个点。 然后突出显示人口众多(> 1M)的城市 library(sp) library(maps) data(canada.cities) head
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它. 6年前关闭。 Improve this
如何保持.txt文件中存在的空格?在.txt文件中,它表示: text :text text1 :text1 text23 :text2 text345 :text3 如果我写这段
以下哪个键最大? 选项 1:16 个数字 [0,9] 选项 2:30 个元音 选项 3:字母表中的 16 个字母 选项 4:32 位 有人可以帮助我,告诉我哪一个是正确的答案以及我们如何计算它吗?我知
在 Unity 3d 中使用 Azure 空间 anchor 来实现在 iOS 和 Android 上部署的室内和室外增强现实体验是否有益? 最佳答案 是的,对于 Azure Spatial Anch
我有一个绝对定位的圆形图像。图像只需占据屏幕宽度的 17%,并且距离顶部 5 个像素。 问题是,当我调整图像大小以占据屏幕宽度的 17% 时,它会这样做,但同时容器会变长。图像本身不会拉伸(stret
我在 Ubuntu 14.04 上使用 Cassandra。从文档中,我可以看到运行命令: nodetool snapshot 创建我的 key 空间的快照。 命令的输出是: nodetool sn
Heroku引入了“私有(private)空间”,是否可以将现有应用迁移到私有(private)空间? https://blog.heroku.com/archives/2015/9/10/herok
是否允许在语义记录中使用非绑定(bind)空格 或其他 HTML 编码字符?我遇到的问题是 ; 字符被软件视为记录的结尾。 例如:假设我有一份婚姻记录,其中包含 2 个结婚者的姓氏、结婚年份以及结
我正在研究“智能 parking ”项目,偶然发现了包含我们真正需要的YouTube视频。我们已经实现了第一部分,即从视频源进行实时透视变换,下一步是将其定义为一组矩形 我基本上需要知道他是如何做到的
我有两个类:Engine 和 Trainset(多个单元),这两个类共享其 ID 空间,其中包含名称和系列 id=- . 这是我的Engine类(它是抽象的,因为有引擎的子类型(DieselEngin
如果有人能帮助我,那就太好了。 我正在尝试使用Java的Split命令,使用空格分割字符串,但问题是,字符串可能没有空格,这意味着它将只是一个简单的顺序(而不是“输入2”将是“退出”) Scanner
我是一名优秀的程序员,十分优秀!