免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3735 | 回复: 6
打印 上一主题 下一主题

[内核入门] 请教:netlink从内核向用户层发数据 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-06-03 21:03 |只看该作者 |倒序浏览
最近需要将显卡中断信息从内核层提到用户层,显卡每次中断用户层都需要要获得其一些寄存器值,直接在内核中写模块,导出一个函数给中断handler调用,在函数里使用netlink_broadcast广播。现在问题是把netlink_broadcast注释掉一点问题没有,只要执行 netlink_broadcast,刚开机就黑屏;我设一计数器,在中断1000次时调用netlink_broadcast(开机过程大约800次左右),屏幕直接变黑。
代码如下:             函数kernel_girq_to_user给中断handler调用

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/kthread.h>
#include <linux/slab.h>
#include <net/sock.h>
#include <net/net_namespace.h>

MODULE_LICENSE("GPL");

#define MAX_MSGSIZE        1024
struct sock *nl_sk= NULL;

int kernel_girq_to_user(struct gpu_irqinfo *g_irqmsg)
{
        struct sk_buff *nl_skb;
        struct nlmsghdr *nlh;
        static int cc = 0;
        int ret = 0;

        if(!nl_sk)
                return -1;

        nl_skb = alloc_skb(NLMSG_SPACE(MAX_MSGSIZE), GFP_KERNEL);
        if(!nl_skb){
                printk("netlink: alloc_skb Error.\n");
        }

        nlh = nlmsg_put(nl_skb, 0, 0, 0, MAX_MSGSIZE, 0);
   
        NETLINK_CB(nl_skb).portid = 0;
        NETLINK_CB(nl_skb).dst_group = GPUIRQ_GROUP;
        memcpy(NLMSG_DATA(nlh), g_irqmsg, sizeof(struct gpu_irqinfo));

//        if(0 == (cc % 1000))
//                ret = netlink_broadcast(nl_sk, nl_skb, 0, GPUIRQ_GROUP, GFP_KERNEL);
        printk("[%s]----------------->>> cc = %d, ret = %d\n", __func__, cc++, ret);

        kfree_skb(nl_skb);
        nl_skb = NULL;

        return 0;
}
EXPORT_SYMBOL(kernel_girq_to_user);

static int __init gpuirq_init(void)
{
        struct netlink_kernel_cfg cfg = {
                .groups        = 1,
                .flags        = NL_CFG_F_NONROOT_RECV,
        };

        nl_sk = netlink_kernel_create(&init_net, NETLINK_GIRQ_MSG, &cfg);
        if(!nl_sk)
                printk("create kernel gpu irq scoket failed!!!\n");
   
        return 0;
}

static void __exit gpuirq_exit(void)
{
        netlink_kernel_release(nl_sk);
        return;
}

module_init(gpuirq_init);
module_exit(gpuirq_exit);

急用!!!多谢

论坛徽章:
0
2 [报告]
发表于 2014-06-04 09:00 |只看该作者
netlink_broadcast会自己kfree_skb.你无需使用kfree_skb

论坛徽章:
0
3 [报告]
发表于 2014-06-04 09:54 |只看该作者
多谢奇门兄的建议,确实,将kfree_skb去掉就可以了。
现在碰到一个新问题,我的这个发送函数是给中断handler调用的,我调试了,只要在handler函数中申请空间,偶尔就会出现bug(虽然不影响netlink发送),或是调用几次,几十会出现一次。message如下:
Jun  1 16:26:53 wangs-gpu kernel: ----------------->>> cc = 774, irq = 0, ret = -3
Jun  1 16:26:53 wangs-gpu kernel: BUG: scheduling while atomic: swapper/0/0/0x10010000
Jun  1 16:26:53 wangs-gpu kernel: Modules linked in: fuse ebtable_nat ebtables ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_nat xt_CHECKSUM iptable_mangle bridge autofs4 sunrpc 8021q garp stp llc cpufreq_ondemand ipt_REJECT nf_conntrack_ipv4 nf_defrag_ipv4 iptable_filter ip_tables ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables ipv6 vhost_net macvtap macvlan tun uinput iTCO_wdt iTCO_vendor_support sg acpi_cpufreq freq_table mperf coretemp kvm_intel kvm crc32c_intel ghash_clmulni_intel cryptd microcode pcspkr serio_raw i2c_i801 lpc_ich mfd_core r8169 mii snd_hda_codec_realtek snd_hda_intel snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm snd_timer snd soundcore snd_page_alloc ext4(F) jbd2(F) mbcache(F) sr_mod(F) cdrom(F) sd_mod(F) crc_t10dif(F) ahci(F) libahci(F) i915(F) drm_kms_helper(F) drm(F) i2c_algo_bit(F) i2c_core(F) gnetlink(F) video(F) dm_mirror(F) dm_region_hash(F) dm_log(F) dm_mod(F)
Jun  1 16:26:53 wangs-gpu kernel: Pid: 0, comm: swapper/0 Tainted: GF       W    3.9.7 #44
Jun  1 16:26:53 wangs-gpu kernel: Call Trace:
Jun  1 16:26:53 wangs-gpu kernel: <IRQ>  [<ffffffff81089240>] __schedule_bug+0x50/0x60
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8155a39c>] __schedule+0x66c/0x720
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8108d32a>] __cond_resched+0x2a/0x40
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8155a4e0>] _cond_resched+0x30/0x40
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff81170de5>] kmem_cache_alloc_trace+0xf5/0x1d0
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffffa00d29da>] ironlake_irq_handler+0xca/0x420 [i915]
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff810e138d>] handle_irq_event_percpu+0x6d/0x210
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff810e1572>] handle_irq_event+0x42/0x70
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff810e4cb9>] handle_edge_irq+0x69/0x120
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff810164bc>] handle_irq+0x5c/0x150
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8105edd3>] ? _local_bh_enable+0x13/0x20
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8105f5a1>] ? irq_enter+0x71/0x80
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8156641d>] do_IRQ+0x5d/0xe0
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8155c02d>] common_interrupt+0x6d/0x6d
Jun  1 16:26:53 wangs-gpu kernel: <EOI>  [<ffffffff810b0124>] ? clockevents_program_event+0x74/0x120
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8144a0d0>] ? cpuidle_wrap_enter+0x50/0x90
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8144a0c9>] ? cpuidle_wrap_enter+0x49/0x90
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8144a120>] cpuidle_enter_tk+0x10/0x20
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff81449b27>] cpuidle_enter_state+0x17/0x50
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8144a36a>] cpuidle_idle_call+0xaa/0x110
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff8101cd0f>] cpu_idle+0xcf/0x120
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff81545655>] rest_init+0x75/0x80
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff81b10235>] start_kernel+0x41e/0x42b
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff81b0fc35>] ? repair_env_string+0x5b/0x5b
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff81b0f5f1>] x86_64_start_reservations+0x2a/0x2c
Jun  1 16:26:53 wangs-gpu kernel: [<ffffffff81b0f737>] x86_64_start_kernel+0x144/0x153

若是将申请socket buffer的函数放在gpuirq_init内,只能申请一次,第一次中断调用就被netlink_broadcast释放了,根本就开不了机。各位大神有没有好的解决方案。

论坛徽章:
0
4 [报告]
发表于 2014-06-04 10:56 |只看该作者
你能说说你怎么申请的内存吗?

论坛徽章:
0
5 [报告]
发表于 2014-06-04 11:03 |只看该作者
看你的panic 发现 内核中断中处理的你的handler ,此时如果申请内存的话只能 GFP_ATOMIC,否则在中断中休眠肯定会导致问题的

论坛徽章:
0
6 [报告]
发表于 2014-06-04 11:43 |只看该作者
多谢,就是那个原因回复 2# 奇门遁甲-lu


   

论坛徽章:
0
7 [报告]
发表于 2014-06-04 11:44 |只看该作者
多谢,调试结果确实是因为没有使用GFP_ATOMIC回复 5# whk547502462


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP