Qt 从Qt 4.4 版本开始提供QSharedMemory类,可以实现Qt程序之间通过共享内存互通,Qt与非Qt程序通过共享内存互通.
void setKey(const QString &key)
void setNativeKey(const QString &key)
共享内存的key需要通过以上函数来设置, 对于两个Qt程序来说,使用setkey设置同一个字符串即可,而对于Qt与非Qt程序通信来说,,需要使用setNativekey. 对Qt程序需要传入一个字符串const QString &key, 而非Qt程序(比如C程序)一般需要使用ftok来创建key值,而ftok的返回值为int类型,非字符串类型,此时Qt程序的setNativekey因参数类型不匹配, 不能建立起与C程序的桥梁,进而无法实现共享内存通信.
key_t key = ftok("stringname",'A');//返回值为int类型
shmid = shmget(key, 4096, IPC_CREAT | IPC_EXCL | 0666);
在用linux 的C程序写共享内存时,基于System V的通信需要设置key,查看Qt源码, 其内部自带ftok功能, 但帮助文档并没有说明, Qt源码中对于 System V 的共享内存创建采用ftok("name","Q")来完成,其ftok 的第二个参数固定为'Q'. 此时我们需要改一下我们的C代码
key_t key = ftok("stringname",'Q');//第二个参数改为'Q'
shmid = shmget(key, 4096, IPC_CREAT | IPC_EXCL | 0666);
此时Qt程序的setNativeKey直接传入第一个参数("stringname")即可
setNativeKey("stringname");
----------------------------------------------------------------------------------------------------------------------------
对于信号量,Qt提供QSemaphore类和QSystemSemaphore类
两种的区别是:QSemaphore是轻量级信号量类, 同于线程间同步,QSystemSemaphore是重量级信号量类,可用于线程和进程间的同步.
对于Qt程序和非程序程序通信时,若使用信号量,需要使用QSystemSemaphore类 ,信号量的key需要通过setKey来设置, 和共享内存一样,Qt将ftok的第二个定死为"Q", 所以我们在创建C程序时需要和其保持一致.
void setKey(const QString &key, int initialValue = 0, AccessMode mode = Open)
在使用中发现Qt的信号量存在一定Bug, 两个Qt程序之间使用信号量完全没有问题,但是在Qt程序与非Qt程序之间使用信号量时,即使设置了相同的key,相同的semid, Qt通过acquire()函数还是获取不到资源一直阻塞.
该问题暂时无法解决,应该是Qt官方对信号量的适配性做的不好,好在Qt 支持C代码的开发,我们直接将C代码挪到Qt程序中进行编译, 不要使用Qt自带的类即可解决.
//cpp文件
int Service::sem_init(key_t key, int val)
{
union semun un;
semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);
if (semid < 0)
{
if (errno == EEXIST)
semid = semget(key, 1, 0666);
else
{
perror("error");
return -1;
}
}
else
{
un.val = val;
semctl(semid, 0, SETVAL, un);
}
return semid;
}
void Service::sem_op(int semid, int op)
{
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = op;
buf.sem_flg = 0;
semop(semid, &buf, 1);
}
//.h文件
private:
union semun
{
int val;
};