精华内容
下载资源
问答
  • 运行在用户上下文环境中的代码是可以阻塞的,这样,便可以使用消息队列和 UNIX 域套接字来实现内核态与用户态的通信。但这些方法的数据传输效率较低,Linux 内核提供 copy_from_user()/copy_to_user() 函数来实现...


      运行在用户上下文环境中的代码是可以阻塞的,这样,便可以使用消息队列和 UNIX 域套接字来实现内核态与用户态的通信。但这些方法的数据传输效率较低,Linux 内核提供 copy_from_user()/copy_to_user() 函数来实现内核态与用户态数据的拷贝,但这两个函数会引发阻塞,所以不能用在硬、软中断中。一般将这两个特殊拷贝函数用在类似于系统调用一类的函数中,此类函数在使用中往往"穿梭"于内核态与用户态。此类方法的工作原理路如图【1】。

    图【1】

    其中相关的系统调用是需要用户自行编写并载入内核。

    内核模块注册了一组设置套接字选项的函数使得用户空间进程可以调用此组函数对内核态数据进行读写。源码包含三个文件,imp1.h 是通用头文件,定义了用户态和内核态都要用到的宏。imp1_k.c 是内核模块的源代码。imp1_u.c 是用户态进程的源代码。整个示例演示了由一个用户态进程向用户上下文环境发送一个字符串,内容为"a message from userspace\n"。然后再由用户上下文环境向用户态进程发送一个字符串,内容为"a message from kernel\n"。

    1 内核代码:

    /*imp1_k.c*/
      2 #ifndef __KERNEL__
      3 #define __KERNEL__
      4 #endif
      5 
      6 #ifndef MODULE
      7 #define MODULE
      8 #endif
      9 
     10 #include <linux/module.h>
     11 #include <linux/kernel.h>
     12 #include <linux/types.h>
     13 #include <linux/string.h>
     14 #include <linux/netfilter_ipv4.h>
     15 #include <linux/init.h>
     16 #include <asm/uaccess.h>
     17 #include "imp1.h"
     18 
     19 #define KMSG      "a message from kernel\n"
     20 #define KMSG_LEN  sizeof("a message from kernel\n")
     21 MODULE_LICENSE("Dual BSD/GPL");
     22 static int data_to_kernel(struct sock *sk, int cmd, void *user,
     23               unsigned int len)
     24 {
     25   switch(cmd)
     26     {
     27     case IMP1_SET:
     28       {
     29         char umsg[64];
     30     memset(umsg, 0, sizeof(char)*64);
     31         copy_from_user(umsg, user, sizeof(char)*64);
     32         printk("umsg: %s", umsg);
     33       }
     34       break;
     35     }
     36   return 0;
     37 }
     38 
     39 static int data_from_kernel(struct sock *sk, int cmd, void *user, int *len)
     40 {
     41   switch(cmd)
     42     {
     43     case IMP1_GET:
     44       {
     45         copy_to_user(user, KMSG, KMSG_LEN);
     46       }
     47       break;
     48     }
     49   return 0;
     50 }
     51 
     52 static struct nf_sockopt_ops imp1_sockops =
     53 {
     54   .pf = PF_INET,
     55   .set_optmin = IMP1_SET,
     56   .set_optmax = IMP1_MAX,
     57   .set = data_to_kernel,
     58   .get_optmin = IMP1_GET,
     59   .get_optmax = IMP1_MAX,
     60   .get = data_from_kernel,
     61 };
     62 
     63 static int __init init(void)
     64 {
     65   return nf_register_sockopt(&imp1_sockops);
     66 }
     67 
     68 static void __exit fini(void)
     69 {
     70   nf_unregister_sockopt(&imp1_sockops);
     71 }
     72 
     73 module_init(init);
     74 module_exit(fini);
     75                          
    
    


    二 应用层代码:

    /*imp1_u.c*/
      2 #include <unistd.h>
      3 #include <stdio.h>
      4 #include <sys/socket.h>
      5 #include <linux/in.h>
      6 #include "imp1.h"
      7 
      8 #define UMSG      "a message from userspace\n"
      9 #define UMSG_LEN  sizeof("a message from userspace\n")
     10 
     11 char kmsg[64];
     12 
     13 int main(void)
     14 {
     15   int sockfd;
     16   int len;
     17 
     18   sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
     19   if(sockfd < 0)
     20     {
     21       printf("can not create a socket\n");
     22       return -1;
     23     }
     24 
     25   /*call function data_to_kernel()*/
     26   setsockopt(sockfd, IPPROTO_IP, IMP1_SET, UMSG, UMSG_LEN);
     27 
     28   len = sizeof(char)*64;
     29 
     30   /*call function data_from_kernel()*/
     31   getsockopt(sockfd, IPPROTO_IP, IMP1_GET, kmsg, &len);
     32   printf("kmsg: %s", kmsg);
     33 
     34   close(sockfd);
     35   return 0;
     36 }


    三头文件:

      1 /*imp1.h*/
      2 #ifndef __IMP1_H__
      3 #define __IMP1_H__
      4 
      5 #define IMP1_OPS_BASIC  128
      6 #define IMP1_SET        IMP1_OPS_BASIC
      7 #define IMP1_GET        IMP1_OPS_BASIC
      8 #define IMP1_MAX        IMP1_OPS_BASIC+1
      9 
     10 #endif
    ~          


    四 编译后运行结果:

    内核打印:[541380.295993] umsg: a message from userspace
    [541390.819256] umsg: a message from userspace
    [541392.515414] umsg: a message from userspace
    [541393.374753] umsg: a message from userspace
    [541393.967123] umsg: a message from userspace

    应用程序打印:

    /imp1$ sudo ./imp1_u
    kmsg: a message from kernel

     

     

     

     

    展开全文
  • netlink 套接字实现的,例如iprote2网络管理工具,它与内核的交互就全部使用了netlink,著名的内核包过滤框架Netfilter在与用户空间的通读,也在最新版本中改变为netlink,无疑,它将是Linux用户态与内核态交流的...
  • 文章目录消息队列机制发送消息三步走接收消息两步走 消息队列机制 在内核空间开辟一片区域,一个进程将数据传到另一个进程,需要完成2次数据复制。第一次,将一个进程的数据复制到内核中,即从用户态转到内核态。第...

    消息队列机制

    在内核空间开辟一片区域,一个进程将数据传到另一个进程,需要完成2次数据复制。第一次,将一个进程的数据复制到内核中,即从用户态转到内核态。第二次,将内核的数据复制到另一个进程,即从内核态转到用户态。与管道相比,简化了对文件的操作。

    发送消息三步走

    第一步:创建一个对象,msgget。需要定义队列的键值,相当于IPC通信对象中的ID号,需要与其他IPC对象的key不一样,接着还需设置权限、模式。

    第二步:复制“消息”到缓存区,则先定义一个结构体

    #define MAX_TEXT 512
    struct msg_st {
    	long int msg_type;
    	char text[MAX_TEXT];
    };
    

    利用stmncmp函数,将数据复制到msg_st的text中。

    第三步:发送消息,msgsnd。这个函数的倒数第二个参数一般设置为0,则表示按照队列的先进先出规则来发送消息。而设置为 等于 msg_st中msg_type的值,则只发送与msg_type匹配的消息。

    发送消息例程

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/msg.h>
    #include <errno.h>
    
    #define MAX_TEXT 512
    struct msg_st{
    	long int msg_type;
    	char text[MAX_TEXT];
    };
    
    int main()
    {
    	int running = 1;
    	struct msg_st data;
    	char buffer[BUFSIZ];
    	int msgid = -1;
    
    	msgid = msgget((key_t)321, 0666 | IPC_CREAT);
    	if (msgid == -1){
    		fprintf(stderr, "msgget failed with error: %d\n", errno);
    		exit(EXIT_FAILURE);
    	}
    
    	while(running) {
    		printf("Enter some text: ");
    		fgets(buffer, BUFSIZ, stdin);
    		data.msg_type = 1;
    		strcpy(data.text, buffer);
    
    		if (msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1) {
    			fprintf(stderr, "msgsnd failed\n");
    			exit(EXIT_FAILURE);
    		}
    
    		if (strncmp(buffer, "end", 3) == 0)
    			running = 0;
    
    		sleep(1);
    	}
    	exit(EXIT_FAILURE);
    }
    
    

    接收消息两步走

    第一步:创建对象,msgget。主要用来获取相同key值的ID号。

    第二步:接收消息,msgrcv。参数用法与msgsnd类似。

    接收例程

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <sys/msg.h>
    
    struct msg_st {
    	long int msg_type;
    	char text[BUFSIZ];
    };
    
    int main()
    {
    	int running = 1;
    	int msgid = -1;
    	struct msg_st data;
    	long int msgtype = 0;
    
    	msgid = msgget((key_t)321, 0666 | IPC_CREAT);
    	if (msgid == -1) {
    		fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
    		exit(EXIT_FAILURE);
    	}
    
    	
    	while(running) {
    		if (msgrcv(msgid, (void*)&data, BUFSIZ, 2, 0) == -1) {
    			fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
    			exit(EXIT_FAILURE);
    		}
    		printf("You wrote: %s\n", data.text);
    
    		if (strncmp(data.text, "end", 3) == 0)
    			running = 0;
    	}
    
    	if (msgctl(msgid, IPC_RMID, 0) == -1) {
    		fprintf(stderr, "msgctl(IPC_RMID) failed\n");
    		exit(EXIT_FAILURE);
    	}
    	exit(EXIT_FAILURE);
    }
    
    
    
    
    展开全文
  • Linux内核态vhost-net

    2019-06-13 10:51:24
    数据直接从tap,通过vhost-net模块吧报文拷贝到虚拟队列的数据区,客户机接收报文 消息通路是当报文从tap设备到达vhost-net时,通知kvm项客户机发中断,通知客户机接收报文 可见中间省略了qemu,主要时因为qemu...

    数据直接从tap,通过vhost-net模块吧报文拷贝到虚拟队列的数据区,客户机接收报文

    消息通路是当报文从tap设备到达vhost-net时,通知kvm项客户机发中断,通知客户机接收报文

     

    可见中间省略了qemu,主要时因为qemu共享了它的内存空间(一些,不说了,),就解放了它

     

    展开全文
  • 内核态和用户态通信(二)--实现

    千次阅读 2018-01-21 10:56:44
    Linux内核态和用户态进程通信方法的提出和实现 用户上下文环境 运行在用户上下文环境中的代码是可以阻塞的,这样,便可以使用消息队列和Unix域套接字来实现内核态和用户态的通信。但这些的数据传输效率较低,linux...

    本文主要使用netlink套接字实现中断环境与用户态进程通信。 
    系统环境:基于linux 2.6.32.27 和 linux 3.16.36


    Linux内核态和用户态进程通信方法的提出和实现

    用户上下文环境

    运行在用户上下文环境中的代码是可以阻塞的,这样,便可以使用消息队列和Unix域套接字来实现内核态和用户态的通信。但这些的数据传输效率较低,linux内核提供copy_from_user() 和 copy_to_user() 函数来实现内核态与用户态数据的拷贝,但这两个函数会引发阻塞,所以不能用在硬、软中断中。一般将这两个特殊拷贝函数用在类似系统调用一类的函数中,如图, 
    这里写图片描述 
    其中相关的系统调用是需要用户自行编写并载入内核。

    硬、软中断环境

    1. 硬中断和软中断环境与用户态进程无丝毫关系,而且运行过程不能阻塞。 
      软中断、硬中断有一套同步机制 — 自旋锁(spinlock),可以通过自旋锁来实现中断环境和中断环境,中断环境与内核线程的同步,而内核线程是运行在有进程上下文环境中的,这样便可以在内核线程中使用套接字或消息队列来取得用户空间的数据,然后再将数据通过临界区传递给中断过程,如图 
      这里写图片描述 
      因为中断过程不可能无休止地等待用户态进程发送数据,所以要通过一个内核线程来接收用户空间的数据,再通过临界区传给中断过程。中断过程向用户空间的数据发送必须是无阻塞的。这样的通信模型并不令人满意,因为内核线程是和其他用户态进程竞争cpu接收数据的,效率很低,这样中断过程便不能实时地接收来自用户空间的数据。

    2. netlink套接字的通信依据是一个对应于进程的标识,一般定义为该进程的ID。当通信的一端处于中断过程时,该标识为0。当使用 netlink 套接字进行通信,通信的双方都是用户态进程,则使用方法类似于消息队列。但通信双方有一端是中断过程,使用方法则不同。netlink 套接字的最大特点是对中断过程的支持,它在内核空间接收用户空间数据时不再需要用户自行启动一个内核线程,而是通过另一个软中断调用用户事先指定的接收函数。工作原理如图 
      这里写图片描述 
      很明显,这里使用了软中断而不是内核线程来接收数据,这样就可以保证数据接收的实时性。 
      当 netlink 套接字用于内核空间与用户空间的通信时,在用户空间的创建方法和一般套接字使用类似,但内核空间的创建方法则不同。如图 
      这里写图片描述


    /**
     *imp2.h
     */
    #ifndef __IMP2_H__
    #define __IMP2_H__
    
    #define IMP2_OPS_BASIC 128
    #define IMP2_SET    IMP2_OPS_BASIC
    #define IMP2_GET    IMP2_OPS_BASIC
    #define IMP2_MAX    (IMP2_OPS_BASIC + 1)
    
    #define IMP2_U_PID 0
    #define IMP2_K_MSG 1
    #define IMP2_CLOSE 2
    
    #define NL_IMP2    31
    
    struct packet_info
    {
        __u32 src;
        __u32 dest;
    };
    #endif
    /**
     *imp2_u.c
     */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <signal.h>
    #include <arpa/inet.h>
    #include <linux/types.h>
    #include <linux/netlink.h>
    #include "imp2.h"
    
    
    struct msg_to_kernel
    {
        struct nlmsghdr hdr;
    };
    
    struct u_packet_info
    {
        struct nlmsghdr hdr;
        struct packet_info icmp_info;
    };
    
    static int skfd;
    
    static void sig_int(int signo)
    {
        struct sockaddr_nl kpeer;
        struct msg_to_kernel message;
    
        memset(&kpeer,0,sizeof(kpeer));
        kpeer.nl_family = AF_NETLINK;
        kpeer.nl_pid = 0;
        kpeer.nl_groups = 0;
    
        memset(&message,0,sizeof(message));
        message.hdr.nlmsg_len = NLMSG_LENGTH(0);
        message.hdr.nlmsg_flags = 0;
        message.hdr.nlmsg_type = IMP2_CLOSE;
        message.hdr.nlmsg_pid = getpid();
    
        sendto(skfd,&message,message.hdr.nlmsg_len,0,(struct sockaddr *)(&kpeer),sizeof(kpeer));
    
        close(skfd);
        exit(0);
    
    }
    
    int main(void)
    {
    
        /* 本地的 */
        struct sockaddr_nl local;
        /* 连线kernel的 */
        struct sockaddr_nl kpeer;
        int kpeerlen;
        struct msg_to_kernel message;
        struct u_packet_info info;
        int sendlen = 0;
        int rcvlen = 0;
        struct in_addr addr;
    
        skfd = socket(AF_NETLINK,SOCK_RAW,NL_IMP2);
        if(skfd < 0) {
            printf("cannot create a netlink socket\n");
            exit(0);
        }
    
        memset(&local,0,sizeof(local));
        local.nl_family = AF_NETLINK;
        local.nl_pid = getpid();
        local.nl_groups = 0;
    
        if(bind(skfd,(struct sockaddr *)&local,sizeof(local)) != 0) {
            printf("bind() error\n");
            return -1;
        }
    
        signal(SIGINT,sig_int);
    
        memset(&kpeer,0,sizeof(kpeer));
        kpeer.nl_family = AF_NETLINK;
        kpeer.nl_pid = 0;
        kpeer.nl_groups = 0;
    
        memset(&message,0,sizeof(message));
        message.hdr.nlmsg_len = NLMSG_LENGTH(0);
        message.hdr.nlmsg_flags = 0;
        message.hdr.nlmsg_type = IMP2_U_PID;
        message.hdr.nlmsg_pid = local.nl_pid;
    
        sendto(skfd,&message,message.hdr.nlmsg_len,0,(struct sockaddr *)&kpeer,sizeof(kpeer));
    
        while(1) {
            kpeerlen = sizeof(struct sockaddr_nl);
            rcvlen = recvfrom(skfd,&info,sizeof(struct u_packet_info),0,(struct sockaddr *)&kpeer,&kpeerlen);
            addr.s_addr = info.icmp_info.src;
            printf("src:%s,",inet_ntoa(addr));
            addr.s_addr = info.icmp_info.dest;
            printf("dest:%s\n",inet_ntoa(addr));
        }
    
        return 0;
    }
    /**
     * imp2_k.c //兼容linux 2.6.32 和 linux 3.16.36
     */
    #ifndef __KERNEL__
    #define __KERNEL__
    #endif
    
    #ifndef MODULE
    #define MODULE
    #endif
    
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/types.h>
    #include <linux/netdevice.h>
    #include <linux/skbuff.h>
    #include <linux/version.h>
    #include <linux/netfilter_ipv4.h>
    #include <linux/inet.h>
    #include <linux/in.h>
    #include <linux/ip.h>
    #include <linux/netlink.h>
    #include <linux/spinlock.h>
    #include <linux/semaphore.h>
    #include <linux/semaphore.h>
    #include <net/sock.h>
    #include "imp2.h"
    
    #define NF_IP_PRE_ROUTING 0
    
    
    /* 实现从netfilter的NF_IP_PRE_ROUTING点截获的ICMP数据包,
       再将数据包的相关信息传递到一个用户态进程 */
    
    static struct sock *nlfd;
    
    //是竞争的资源
    struct {
        __u32 pid;
        rwlock_t lock;
    }user_proc;
    
    
    
    //相当于np_log
    static int send_to_user(struct packet_info *info)
    {
        int ret = 0;
        int size = 0;
        unsigned char *old_tail = NULL;
    
        struct sk_buff *skb = NULL;
        struct nlmsghdr *nlh = NULL;
        struct packet_info *packet = NULL;
    
        printk("%s,begin ....\n",__FUNCTION__);
    
        size = NLMSG_SPACE(sizeof(*info));
        //分配一块skb(数据缓存区和skb描述符),大小,GFP自动分配
        skb = alloc_skb(size,GFP_ATOMIC);
        old_tail = skb->tail;
    
        nlh = nlmsg_put(skb,0,0,IMP2_K_MSG,(size-sizeof(*nlh)),0);
        packet = NLMSG_DATA(nlh);
        memset(packet , 0 ,sizeof(struct packet_info));
    
        packet->src = info->src;
        packet->dest = info->dest;
    
        nlh->nlmsg_len = skb->tail - old_tail;
        NETLINK_CB(skb).dst_group = 0;
    
        read_lock_bh(&user_proc.lock);
        ret = netlink_unicast(nlfd,skb,user_proc.pid,MSG_DONTWAIT);
        read_unlock_bh(&user_proc.lock);
    
        printk("%s,end....\n",__FUNCTION__);
    
        return ret;
    
    nlmsg_failure:
    
        if(skb) {
            kfree_skb(skb);
        }
        return -1;
    }
    
    
    static unsigned int get_icmp(unsigned int hooknum,struct sk_buff *skb,
            const struct net_device *in,const struct net_device *out,
            int(*okfn)(struct sk_buff *))
    {
        //struct iphdr *iph = (*pskb)->nh.iph;
        struct iphdr *iph = ip_hdr(skb);    //2.6.24开始使用,因为struct sk_buff
        struct packet_info info;
    
    
        if(iph->protocol == IPPROTO_ICMP) {
            read_lock_bh(&user_proc.lock);
    
            if(user_proc.pid != 0) {
                info.src = iph->saddr;
                info.dest= iph->daddr;
    
                //printk("%s,src = %u.%u,%u.%u,dst = %u,%u,%u,%u\n",__FUNCTION__,NIPQUAD(info.src), NIPQUAD(info.dest));
    
                read_unlock_bh(&user_proc.lock);
    
                send_to_user(&info);
    
            } else {
                //printk("%s, no user process runing....\n",__FUNCTION__);
                read_unlock_bh(&user_proc.lock);
    
            }
        }
    
        return NF_ACCEPT;
    }
    
    
    static struct nf_hook_ops imp2_ops = 
    {
        .hook = get_icmp,
        .pf = PF_INET,
        .hooknum = NF_IP_PRE_ROUTING,
        .priority = NF_IP_PRI_FILTER - 1,
        .owner = THIS_MODULE,
    };
    
    static void kernel_receive(struct sk_buff *skb)
    {
        struct nlmsghdr *nlh = NULL;
        int len = 0;
    
        nlh = nlmsg_hdr(skb);
        len = skb->len;
    
        while(NLMSG_OK(nlh,len)) {
    
            write_lock_bh(&user_proc.lock);
    
            if(nlh->nlmsg_type == IMP2_U_PID) {
                user_proc.pid = nlh->nlmsg_pid;
            }
            else if(nlh->nlmsg_type == IMP2_CLOSE && nlh->nlmsg_pid == user_proc.pid) {
                user_proc.pid = 0;
            }
    
            write_unlock_bh(&user_proc.lock);
    
            netlink_ack(skb,nlh,0);
            nlh = NLMSG_NEXT(nlh,len);
        }
    }
    
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
    
    struct netlink_kernel_cfg cfg = 
    {
        .input = kernel_receive,
    };
    
    #endif
    
    static int __init init(void)
    {
        rwlock_init(&user_proc.lock);
    
        //这里的版本问题需要解决
        /*在内核创建一个netlink socket ,
          协议 NL_IMP2是自定义的,并指示由 kernel_receive接收数据*/
    
        {
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
            nlfd = netlink_kernel_create(&init_net,NL_IMP2,&cfg);
    #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) 
            nlfd = netlink_kernel_create(&init_net ,NL_IMP2 , 0, kernel_receive, NULL, THIS_MODULE);
    
    #else 
            nlfd = NULL;
    
    #endif
        }
    
    
        if(!nlfd) {
            printk("cannot create a netlink socket\n");
            return -1;
        }
    
        return nf_register_hook(&imp2_ops);
    }
    
    
    static void __exit fini(void)
    {
        if(nlfd) {
            netlink_kernel_release(nlfd);
        }
    
        nf_unregister_hook(&imp2_ops);
    }
    
    
    
    module_init(init);
    module_exit(fini);
    MODULE_LICENSE("GPL");
    
    #Makefile
    MODULE_NAME := imp2_k
    obj-m := $(MODULE_NAME).o
    
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)
    
    all: 
        $(MAKE) -C $(KERNELDIR) M=$(PWD)
    
    clean:
        rm -fr *.ko
        rm -fr *.o 
        rm -fr *.cmd sender $(MODULE_NAME).mod.c
    
    
    .PHONY:clean aLL

    netlink具体结构分析,可参考其他博文 
    http://blog.csdn.net/luckyapple1028/article/details/50839395 

    http://blog.csdn.net/luckyapple1028/article/details/50936563

    转自:http://blog.csdn.net/my_zou/article/details/53840840

    展开全文
  • Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存参考:《linux编程从入门到精通》,《Linux C程序设计大全》,《unix环境高级编程》参考:C和指针学习 说明:本文非常的长,也是为了便于查找和比较,...
  • 1、概述 ...消息队列 在硬、软中断中无法无阻塞地接收数据。 信号量 无法介于内核态和用户态使用。 内存共享 需要信号量辅助,而信号量又无法使用。 套接字 在硬、软中断中无法无阻
  • Linux包含了在其他UNIX系统中出现的所有并发机制,其中包括管道、消息队列、共享内存和信号,除此之外,Linux2.6还包含了一套丰富的并发机制,这套机制是特别为内核态线程准备的。换言之,它们是内核中的并发机制,...
  • 管道通信:这种通信方式,涉及两次用户态与内核态之间的拷贝,将数据写入管道,再从管道中读取数据。 共享内存:直接通过虚拟地址访问物理内存实现对共享内存中数据的操作,相比与管道通信少了两次用户态与内...
  • 3、消息:允许进程在预定义的消息队列中读和写消息来交换消息(小块数据)。Linux提供两种不同的消息版本:System V IPC;POSIX消息4、共享内存区:允许进程通过共享内存块来交换信息。在必须共享大量数据的应用...
  • 参考:《linux编程从入门到精通》,《Linux C程序设计大全》,《unix环境高级编程》 ...Linux 传统的进程间通信有很多,如各类管道、消息队列、内存共享、信号量等等。但它们都无法介于内核态与用户态使用...
  • 消息队列、socket:copy_from_user()/copy_to_user() 以上同步通信方式,由用户态主动发起向内核态的通信,内核无法主动发起通信 netlink:异步全双工的通信方式,它支持由内核态主动发起通信,内核为Netlink通信...
  • 通信过程需要用户态到内核态,再到用户态的情况。 特性: (1).半双工通信方式,(可双向传递数据,同一时刻只能单向) (2).生命周期随进程,进程退出,管道释放。 (3).以只读方式打开会阻塞,直到文件以写的...

空空如也

空空如也

1 2 3
收藏数 52
精华内容 20
关键字:

linux内核态消息队列

linux 订阅