信號量+(有名,非匿名)共享內存使用示例:
#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);
}
}