Linux信號量+共享內存(有名,非匿名)使用示例

信號量+(有名,非匿名)共享內存使用示例:

#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);
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章