信号量+(有名,非匿名)共享内存使用示例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#include <sys/sem.h>
#include <syslog.h>
#define MAX_SIZE 4096
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
enum KEY_STAT{
NONE,
KEY_ON,
KEY_OFF,
};
struct wdt_share_mem{
unsigned int timeleft; //单位:秒
enum KEY_STAT key_stat;
};
struct wdt_private_data{
key_t key;
int shmid;
int semid;
union semun union_sem;
struct wdt_share_mem *wdt_shm;
};
static int sem_p(int id)
{
int ret;
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = -1;
buf.sem_flg = SEM_UNDO;
ret = semop(id, &buf, 1);
if(-1 == ret){
syslog(LOG_USER|LOG_ERR, "semop");
return -1;
}
return 0;
}
static int sem_v(int id)
{
int ret;
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = 1;
buf.sem_flg = SEM_UNDO;
ret = semop(id, &buf, 1);
if(-1 == ret){
syslog(LOG_USER|LOG_ERR, "semop");
return -1;
}
return 0;
}
int wdt_init(struct wdt_private_data *priv)
{
int ret = 0;
priv->key = ftok("/dev/null", 'p');
/* 信号量申请 */
priv->semid = semget(priv->key, 1, IPC_CREAT);
if(-1 == priv->semid){
syslog(LOG_USER|LOG_ERR, "semget");
return -1;
}
/* 信号量初始化 */
priv->union_sem.val = 1;
ret = semctl(priv->semid, 0, SETVAL, priv->union_sem);
if(-1 == ret)
{
syslog(LOG_USER|LOG_ERR, "semctl");
return -1;
}
/* 共享内存申请 */
priv->shmid = shmget(priv->key, MAX_SIZE, 0666 | IPC_CREAT);
if(priv->shmid == -1){
syslog(LOG_USER|LOG_ERR, "wdt shm get error!");
return -1;
}
priv->wdt_shm = (struct wdt_share_mem *)shmat(priv->shmid, NULL, 0);
/* 共享内存初始化 */
priv->wdt_shm->timeleft = 0; //初始化时间,单位:秒
priv->wdt_shm->key_stat = NONE; //按键键值状态,未定义
return ret;
}
int main(int argc,char *argv[])
{
int ret;
struct wdt_private_data *wdt_priv;
unsigned int secleft;
if(ret = daemon(0, 0)){ //参数1 =0:工作目录将被设置为“/”(根目录),
//参数2 =0:标准输入、标准输出和标准错误输出都被重定向到/dev/null文件
perror("wdt change to daemon err");
exit(-1);
};
wdt_priv = (struct wdt_private_data *)malloc(sizeof(struct wdt_private_data));
if(wdt_priv == NULL){
syslog(LOG_USER|LOG_ERR, "wdt malloc error!");
exit(-1);
}
if((ret = wdt_init(wdt_priv)) < 0){
exit(-1);
}
system("echo 0 > ./a.txt"); //do something
for(;;){
sem_p(wdt_priv->semid);
secleft = wdt_priv->wdt_shm->timeleft;
if(secleft <= 0){
sem_v(wdt_priv->semid);
system("echo 0 > ./a.txt"); //do something
while(1){
sem_p(wdt_priv->semid);
secleft = wdt_priv->wdt_shm->timeleft;
sem_v(wdt_priv->semid);
if(secleft > 0){
system("echo 1 > ./a.txt"); //do something
break;
}
sleep(1);
}
}else{
secleft -= 1;
wdt_priv->wdt_shm->timeleft = secleft;
sem_v(wdt_priv->semid);
}
sleep(1);
}
}