线程及进程的同步 可以使用 信号量, 信号的方法。
但实际使用过程中遇到一个难题,就是 sem_timedwait 使用的是绝对时间, 如果timedwait过程中修改系统时间则会出现异常, timeout 提前退出或timeout 到期后还无法退出。
原来的方法:
线程同步使用pthread_cond+ mutex的方法可以参考如下文章。
https://blog.csdn.net/wys7250578/article/details/46859961
线程同步使用信号量: (如果将信号量设置为进程共享,应该也适用于进程同步,需要研究可行性)
sem_init //可以设置进程共享。
sem_destroy
sem_post
sem_getvalue
sem_wait
sem_trywait
sem_timedwait
进程同步信号量 需要使用下面接口:
semget
semctl
semop
实际上cond + mutex的方法 可以设置使用相对时间, 同时通过设置属性也可以用于进程间共享。
以这段代码为例, 不论是进程还是线程同步,都可以使用pthread_condattr_setclock(&ca, CLOCK_MONOTONIC);
采用相对时间而不用绝对时间,避免系统时间修改的影响。
同时可以设置cond及mutex的属性为 PTHREAD_PROCESS_SHARED, 这样mutex和cond 可以进程间共享。
但前提是 mutex和cond 必须创建在共享内存, 同时通过测试发现pthread_mutexattr_t、 pthread_condattr_t 可以创建在共享内存,也可以通过临时变量, 下面code是使用临时变量。
下面code 只是一个process, 可以通过另外一个process 发signal
typedef struct _ST_EST_IPC_SHM
{
pthread_mutex_t mutex; //40
pthread_cond_t cond; //48
//pthread_mutexattr_t
pthread_condattr_t condattr; //8
char str[8];
} ST_TEST_IPC_SHM;
static int giPLATVIUMemId = -1;
static char g_cPLATshareMem[20] = "PLAT_TEST2_SHM";
static ST_TEST_IPC_SHM *g_pShareMem = NULL;
//main
printf( "[Process A]pid = %d , ppid = %d\n", getpid(), getppid());
if( (gpPLATVIUShareMem = ShmCreate( &giPLATVIUMemId, g_cPLATshareMem,
sizeof( ST_PLAT_TEST_IPC_SHM ) ) )== FALSE) //Have not Create yet...
g_pShareMem = (ST_PLAT_TEST_IPC_SHM *)(gpPLATVIUShareMem);
//g_pShareMem->mutex;
char teststr2[] = "1234";
sprintf(g_pShareMem->str, "%s", teststr2);
pthread_condattr_t ca; //&(g_pShareMem->condattr)
pthread_condattr_init(&ca);
pthread_condattr_setclock(&ca, CLOCK_MONOTONIC);
pthread_condattr_setpshared(&ca, PTHREAD_PROCESS_SHARED);
if( pthread_cond_init( &(g_pShareMem->cond), &ca) == 0 )
{
ret = -1;
}
pthread_mutexattr_t ma;
pthread_mutexattr_init(&ma);
pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
pthread_mutex_init(&(g_pShareMem->mutex), &ma);
ret = pthread_mutex_lock(&(g_pShareMem->mutex));
printf("[Process A]pthread_mutex_lock ret= %d \n", ret);
if (clock_gettime(CLOCK_MONOTONIC, &u32TSOut) == -1) //CLOCK_REALTIME CLOCK_MONOTONIC
{
printf("[Process A]clock_gettime fail1\n");
}
printf("[Process A] %s, u32TSOut.tv_sec1 = %ld \n", __FUNCTION__, u32TSOut.tv_sec);
u32TSOut.tv_sec += 20;
if ((ret = pthread_cond_timedwait(&(g_pShareMem->cond), &(g_pShareMem->mutex), &u32TSOut)) == 0)
{
ret = 0;
printf("[Process A] pthread_cond_timedwait return 0. \n");
}
else {
printf("[Process A] pthread_cond_timedwait return %d. \n", ret);
}
if (clock_gettime(CLOCK_MONOTONIC, &u32TSOut) == -1) //CLOCK_REALTIME CLOCK_MONOTONIC
{
printf("[Process A]clock_gettime fail2\n");
}
printf("[Process A] %s, u32TSOut.tv_sec2 = %ld \n", __FUNCTION__, u32TSOut.tv_sec);
pthread_mutex_unlock(&(g_pShareMem->mutex));
sleep(1);
printf("[Process A] exit\n");
exit(EXIT_SUCCESS);
}
//process B
ret = pthread_mutex_lock(&(g_pShareMem->mutex));
pthread_cond_signal( &(g_pShareMem->cond) ) ;
ret = pthread_mutex_unlock(&(g_pShareMem->mutex));