进程与进程,进程与内核间通信(netlink)
来源:互联网 发布:江西师大网络教学平台 编辑:程序博客网 时间:2024/05/16 07:17
进程与进程间通信方式IPC:
1. 早期unix IPC:管道,FIFO,信号
2. System V IPC(贝尔实验室): system V消息队列,system V信号灯,system V共享内存
3. socket IPC (BSD)
4. Posix IPC: Posix消息队列,Posix信号灯,Posix共享内存
线程间通信:
1. 全局变量
2. 线程锁
3. pthread_time_wait
进程与内核间通信
1. ioctl()
2. 共享内存:mmap()
3. netlink
4. 其他
其他: 内核启动参数;模块参数;sysfs;procfs;debugfs;relayfs;sysctl;系统调用;copy_from_user()/copy_to_user();get_user()/put_user();信号/信号量/管道等等
netlink可以实现
1. 内核向进程广播(如热插拔事件)
2. 进程与内核双向通信
3. 进程与进程通信。
参考:
Linux 用户态与内核态的交互——netlink 篇:http://bbs.chinaunix.net/thread-2162796-1-1.html
《Linux 系统内核空间与用户空间通信的实现与分析》 陈鑫 http://www-128.ibm.com/developerworks/cn/linux/l-netlink/?ca=dwcn-newsletter-linux
《在 Linux 下用户空间与内核空间数据交换的方式》 杨燚 http://www-128.ibm.com/developerworks/cn/linux/l-kerns-usrs/
http://blog.csdn.net/wangpengqi/article/details/9969599
上: http://blog.chinaunix.net/uid-23069658-id-3400761.html
中: http://blog.chinaunix.net/uid-23069658-id-3405954.html
下: http://blog.chinaunix.net/uid-23069658-id-3409786.html
3.10的内核比2.6的内核,netlink接口函数发生了一些变化。
// 内核态netlink_kernel_create()netlink_unicast()netlink_broadcast()// 用户态socket()bind()sendmsg()recvmsg()close()
进程A和子系统1之间是单播通信,进程B、C和子系统2是多播通信。上图还向我们说明了一个信息。从用户空间传递到内核的数据是不需要排队的,即其操作是同步完成;而从内核空间向用户空间传递数据时需要排队,是异步的。
Netlink消息由两部分组成:消息头和有效数据载荷,且整个Netlink消息是4字节对齐。消息头为固定的16字节,消息体长度可变,采用TLV(Type-Length-Value)格式
// Kernel#define NETLINK_ATC_SUSPEND 30#define PM_NETLINK_GROUP 1#define PM_NETLINK_SUSPEND_KEY "gpio_suspend"#define ENTER_SUSPEND_GPIO 1 // GPIO1static struct sock *netlink_sock = NULL;static int netlink_broadcast(char *msg){ struct sk_buff *skb; struct nlmsghdr *nlh; int len = strlen(msg)+1; printk(KERN_INFO "[%s %d] msg=[%s]\n", __FUNCTION__, __LINE__, msg); if(!msg || !netlink_sock){ return -1; } skb = nlmsg_new(len, GFP_KERNEL); if(!skb){ printk(KERN_ERR "[%s %d] \n", __FUNCTION__, __LINE__); return -1; } nlh = nlmsg_put(skb, 0, 0, 0, len, 0); NETLINK_CB(skb).portid = 0; NETLINK_CB(skb).dst_group = PM_NETLINK_GROUP; memcpy(NLMSG_DATA(nlh), msg, len); printk(KERN_ERR "[%s %d] netlink broadcast msg [%s]\n", __FUNCTION__, __LINE__, msg); return netlink_broadcast(netlink_sock, skb, 0, PM_NETLINK_GROUP, GFP_KERNEL);}static irqreturn_t suspend_gpio_irq_handler(int irq, void *data){ struct gpio_desc *desc = (struct gpio_desc *)data; int gpio = desc_to_gpio(desc); char msg[64]; int ret = 0; snprintf(msg, sizeof(msg), "%s%d", PM_NETLINK_SUSPEND_KEY, gpio); ret = atc_netlink_broadcast(msg); return IRQ_HANDLED;}static int suspend_gpio_request_irq(void){ int gpio = ENTER_SUSPEND_GPIO; struct gpio_desc *desc = gpio_to_desc(gpio); int irq = gpiod_to_irq(desc); if(irq > 0 && gpio_is_valid(gpio)){ #if 0 if(!gpio_suspend_workqueue) { gpio_suspend_workqueue = create_singlethread_workqueue("gpio_wakeup"); INIT_WORK(&atc_gpio_suspend_work, atc_gpio_suspend_work_func); } #else if(!netlink_sock){ struct netlink_kernel_cfg cfg = { .input = NULL, }; extern struct net init_net; netlink_sock = netlink_kernel_create(&init_net, NETLINK_ATC_SUSPEND, &cfg); if(!netlink_sock){ printk(KERN_ERR "[ATC %s %d] netlink_kernel_create fail\n", __FUNCTION__, __LINE__); return -1; } } #endif gpio_direction_input(gpio); irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); /* Regester IRQ */ if(request_irq(irq, suspend_gpio_irq_handler, IRQF_SHARED, PM_NETLINK_SUSPEND_KEY, desc) ) { printk(KERN_ERR "[%s %d] request_irq fail %d\n", __FUNCTION__, __LINE__, irq); } } else{ printk(KERN_ERR "[%s %d] irq(%d) or gpio is not valid\n", __FUNCTION__, __LINE__, irq); } return 0;}// Userstatic void *pm_thread (void *arg){ struct sockaddr_nl src_addr; struct nlmsghdr *nlh = NULL; struct iovec iov; struct msghdr msg; int sock_fd, retval; int fd_count = 0; fd_set rfds, efds; sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_SUSPEND); if(sock_fd < 0){ goto exit; } memset(&src_addr, 0, sizeof(src_addr)); src_addr.nl_family = PF_NETLINK; src_addr.nl_pid = 0; src_addr.nl_groups = 1 << (PM_NETLINK_GROUP - 1); retval = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr)); if (retval < 0) { goto exit; } nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(PM_NETLINK_PAYLOAD_MAX)); if (!nlh) { printf("malloc nlmsghdr %d-%s", errno, strerror(errno)); goto exit; } memset(nlh, 0, NLMSG_SPACE(PM_NETLINK_PAYLOAD_MAX)); iov.iov_base = (void *)nlh; iov.iov_len = NLMSG_SPACE(PM_NETLINK_PAYLOAD_MAX); memset(&msg, 0, sizeof(msg)); msg.msg_iov = &iov; msg.msg_iovlen = 1; FD_ZERO(&rfds); FD_ZERO(&efds); fd_count = sock_fd; while (!pm_thread_quit) { FD_SET(sock_fd, &rfds); FD_SET(sock_fd, &efds); retval = select(fd_count + 1, &rfds, NULL, &efds, NULL); if (retval < 0) { goto exit; } else if (retval == 0) { } else if (FD_ISSET(sock_fd, &rfds)){ if (recvmsg(sock_fd, &msg, 0) > 0) { const char *s = (char*)NLMSG_DATA(nlh); int len = strlen(PM_NETLINK_SUSPEND_KEY); if(!strncmp(s, PM_NETLINK_SUSPEND_KEY, len)) { int pin = atoi(s+len); usleep(100000); if(gpio_get_value(pin) == 1) { printf("state"); } } } } }exit: if(sock_fd > 0) close(sock_fd); pm_thread_id = 0; return NULL;}
net_link.c----------------------------------------------------------------------#include <linux/kernel.h>#include <linux/module.h>#include <linux/types.h>#include <linux/sched.h>#include <net/sock.h>#include <net/netlink.h>#define NETLINK_TEST 21struct sock *nl_sk = NULL;EXPORT_SYMBOL_GPL(nl_sk);void nl_data_ready (struct sk_buff *__skb){ struct sk_buff *skb; struct nlmsghdr *nlh; u32 pid; int rc; int len = NLMSG_SPACE(1200); char str[100]; printk("net_link: data is ready to read.\n"); skb = skb_get(__skb); if (skb->len >= NLMSG_SPACE(0)) { nlh = nlmsg_hdr(skb); printk("net_link: recv %s.\n", (char *)NLMSG_DATA(nlh)); memcpy(str,NLMSG_DATA(nlh), sizeof(str)); pid = nlh->nlmsg_pid; /*pid of sending process */ printk("net_link: pid is %d\n", pid); kfree_skb(skb); skb = alloc_skb(len, GFP_ATOMIC); if (!skb){ printk(KERN_ERR "net_link: allocate failed.\n"); return; } nlh = nlmsg_put(skb,0,0,0,1200,0); NETLINK_CB(skb).pid = 0; /* from kernel */ memcpy(NLMSG_DATA(nlh), str, sizeof(str)); printk("net_link: going to send.\n"); rc = netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT); if (rc < 0) { printk(KERN_ERR "net_link: can not unicast skb (%d)\n", rc); } printk("net_link: send is ok.\n"); } return;}static int test_netlink(void) { nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, 0, nl_data_ready, NULL, THIS_MODULE); if (!nl_sk) { printk(KERN_ERR "net_link: Cannot create netlink socket.\n"); return -EIO; } printk("net_link: create socket ok.\n"); return 0;}int init_module(){ test_netlink(); return 0;}void cleanup_module( ){ if (nl_sk != NULL){ sock_release(nl_sk->sk_socket); } printk("net_link: remove ok.\n");}MODULE_LICENSE("GPL");MODULE_AUTHOR("kidoln");----------------------------------------------------------------------sender.c----------------------------------------------------------------------#include <sys/stat.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <string.h>#include <asm/types.h>#include <linux/netlink.h>#include <linux/socket.h>#define MAX_PAYLOAD 1024 /* maximum payload size*/struct sockaddr_nl src_addr, dest_addr;struct nlmsghdr *nlh = NULL;struct iovec iov;int sock_fd;struct msghdr msg;int main(int argc, char* argv[]){ sock_fd = socket(PF_NETLINK, SOCK_RAW, 21); memset(&msg, 0, sizeof(msg)); memset(&src_addr, 0, sizeof(src_addr)); src_addr.nl_family = AF_NETLINK; src_addr.nl_pid = getpid(); /* self pid */ src_addr.nl_groups = 0; /* not in mcast groups */ bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_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)); /* Fill the netlink message header */ nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); nlh->nlmsg_pid = getpid(); /* self pid */ nlh->nlmsg_flags = 0; /* Fill in the netlink message payload */ strcpy(NLMSG_DATA(nlh), "Hello you!"); iov.iov_base = (void *)nlh; iov.iov_len = nlh->nlmsg_len; msg.msg_name = (void *)&dest_addr; msg.msg_namelen = sizeof(dest_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; printf(" Sending message. ...\n"); sendmsg(sock_fd, &msg, 0); /* Read message from kernel */ memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD)); printf(" Waiting message. ...\n"); recvmsg(sock_fd, &msg, 0); printf(" Received message payload: %s\n",NLMSG_DATA(nlh)); /* Close Netlink Socket */ close(sock_fd);}----------------------------------------------------------------------Makefile----------------------------------------------------------------------MODULE_NAME :=net_linkobj-m :=$(MODULE_NAME).oKERNELDIR ?= /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)all: $(MAKE) -C $(KERNELDIR) M=$(PWD) gcc -o sender sender.cclean: rm -fr *.ko *.o *.cmd sender $(MODULE_NAME).mod.c----------------------------------------------------------------------
- 进程与进程,进程与内核间通信(netlink)
- 用户进程与内核进程通信netlink实例
- 进程与进程间通信
- 进程与进程通信
- 进程与进程间的通信
- (转)进程与进程间通信
- Linux进程、线程与进程间通信
- Qt:进程与进程间通信
- Linux C 进程与进程间通信
- 进程与线程及进程间通信
- VC 进程与进程通信
- 进程与进程通信机制
- 进程控制与进程通信
- linux进程间通信——netlink
- linux进程间通信——netlink
- 指针与进程间通信
- unix内核概述-信号与进程间的通信
- Windows服务与普通进程间通信(通过内核对象)
- GreenDao 使用教程 一
- 高效率http retrofit2.0.2 最新版本
- 修改linux最大连接数
- 选项菜单
- digit-counts
- 进程与进程,进程与内核间通信(netlink)
- led灯点亮
- IntelliJ IDEA 使用心得与常用快捷键
- 链表删除节点--算法复杂度o(1)
- Flume学习11_Flume1.5.0的安装使用及传输数据到Hadoop2.2
- 请求转发与重定向
- 【HDU5543 2015 CCPC 南阳国赛D】【贪心+DP】Pick The Sticks 木棍重心放在容器内 贪心法+三维状态直接法
- Android动画之补间动画
- 原装Win8 改 Win7 出现的问题