当前位置: > 华清远见教育科技集团 > 嵌入式学习 > 讲师博文 > IPC_PRIVATE和ftok的比较
IPC_PRIVATE和ftok的比较
时间:2016-12-12作者:华清远见

在linux中,可以使用IPC对象来进行进程间通信。IPC对象存在于内核中,多进程可以操作同一个IPC对象。

每个IPC对象都有一个唯一的编号,该编号是由系统分配的。那么不同的进程如何知道这个编号,进而通过它进行通信呢?下面以共享内存为例,进行分析。

方法一:通过ftok函数,产生相同的键值。

假设,进程p1创建了共享内存。可以在创建时,调用ftok函数,得到一个key值,调用shmget函数,该函数会返回所创建共享内存的编号,并将key和编号关联起来。若进程p2想利用这个共享内存和p1进程通信,也可以调用ftok函数,得到同样的key,再根据key值,调用shmget函数,就可以获得该共享内存的编号。该过程可以通过下面的图来表达。

ftok函数原型如下:
                #include < sys/types.h>
                #include < sys/ipc.h>
                key_t ftok(const char *pathname, int proj_id);

第一个参数pathname,是一个存在的文件或目录名;

第二个参数proj_id,是非0整数

该函数会返回一个key值,先运行的进程根据key来创建对象,后运行的进程根据key来打开对象。示意图如下:

使用 ftok创建共享内存,毫无关系的进程,可以通过得到同样的key,来操作同一个共享内存,对共享内存进行读写时,需要利用信号量进行同步或互斥。

方法二:使用IPC_PRIVATE对象

使用IPC_PRIVATE创建的IPC对象, key值属性为0,和IPC对象的编号就没有了对应关系。这样毫无关系的进程,就不能通过key值来得到IPC对象的编号(因为这种方式创建的IPC对象的key值都是0)。因此,这种方式产生的IPC对象,和无名管道类似,不能用于毫无关系的进程间通信。但也不是一点用处都没有,仍然可以用于有亲缘关系的进程间通信。示例程序如下:

#include < stdio.h>
        #include < stdlib.h>
        #include < errno.h>
        #include < sys/ipc.h>
        #include < sys/types.h>
        #include < sys/shm.h>
        #include < string.h>
        #define MAXSIZE 1024
        int main()
        {
                int shmid;
                        char *p = NULL;
                        pid_t pid;
                #if 0
                        key_t key;
                        if ((key = ftok(".", 'a')) == -1)
                        {
                                perror("ftok");
                                exit(-1);
                        }
                #endif
                if ((shmid = shmget(IPC_PRIVATE, MAXSIZE, 0666)) == -1)
                {
                        perror("shmget");
                        exit(-1);
                }
                if ((pid = fork()) == -1)
                {
                        perror("fork");
                        exit(-1);
                }
                if (pid == 0)
                {
                        if ((p = shmat(shmid, NULL, 0)) == (void *)-1)
                        {
                                perror("shmat");
                                exit(-1);
                        }
                                strcpy(p, "hello\n");
                        system("ipcs -m");
                                if (shmdt(p) == -1)
                                {
                                perror("shmdt");
                                exit(-1);
                        }
                        system("ipcs -m");
                }
                else
                {
                        getchar();
                                if ((p = shmat(shmid, NULL, 0)) == (void *)-1)
                        {
                                perror("shmat");
                                exit(-1);
                        }
                        printf("%s\n", (char *)p);
                        if (shmctl(shmid, IPC_RMID, NULL) == -1)
                        {
                                perror("RM");
                                exit(-1);
                        }
                }
                return 0;
        }

该程序中,父进程使用IPC_PRIVATE方式创建了共享内存,然后fork产生了子进程,由于子进程是复制父进程的方式产生的,因此,子进程也可以操作共享内存。子进程往共享内存里写了内容后,父进程可以读到。

发表评论
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)