LINUX.ORG.RU

Вопрос по семафорам


0

0


Нужно написать функции для процессов, которые анаогичны функциям pthread_mutex_lock и pthread_mutex_unlock для pthreads, только через семафоры.
Прочитал в ALP про IPC. Возможно не все просек.
Делал так.



/* Obtain a binary semaphore s ID, allocating if necessary. */
int binary_semaphore_allocation (key_t key, int sem_flags) {
return semget (key, 1, sem_flags);
}
/* Deallocate a binary semaphore. All users must have finished their use. Returns -1 on failure. */
int binary_semaphore_deallocate (int semid) {
union semun ignored_argument;
return semctl (semid, 1, IPC_RMID, ignored_argument);
}
int binary_semaphore_initialize (int semid) {
union semun argument;
unsigned short values[1];
values[0] = 1;
argument.array = values;
return semctl (semid, 0, SETALL, argument);
}
/*Это lock*/
int binary_semaphore_wait (int semid) {
struct sembuf operations[1];
/* Use the first (and only) semaphore. */
operations[0].sem_num = 0;
/* Decrement by 1. */
operations[0].sem_op = -1;
/* Permit undo ing. */
operations[0].sem_flg = 0;
return semop(semid, operations, 1);
}

/* Это unlock*/
int binary_semaphore_post (int semid) {
struct sembuf operations[1];
/* Use the first (and only) semaphore. */
operations[0].sem_num = 0;
/* Increment by 1. */
operations[0].sem_op = 1;
/* Permit undo ing. */
operations[0].sem_flg = 0;
return semop (semid, operations, 1);
}

Используется таким макаром.

В предке .
if((mx_hash_semaphore = binary_semaphore_allocation( IPC_PRIVATE, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) < 0 ){
perror("semget");
exit(-1);
}
if(binary_semaphore_initialize(mx_hash_semaphore)<0){
perror("init");
exit(-1);
}

В потомках

binary_semaphore_wait (mx_hash_semaphore);
//Критические действия
binary_semaphore_post (mx_hash_semaphore);


Но при таком раскладе все чилды иногда зависают на wait и не отвисают :((((
Подскажите что-нить полезное....
Задача ведь часто встречающаяся.
Или можете прислать аналогичные функции на v_dav@inbox.ru











★★★★

Могу дать пример использования семафоров в сочетании с записью в файл и шаред мемори. Работает прекрасно при любом количестве процессов (сам запускал при 100 дочерних процессов).
<util.h>
#ifndef _UTIL_H
#define _UTIL_H

#define PERM 0600
#define LOGFILE "/tmp/qstat.log"
int addLog(char *, int);
void clearLog(int);
int createLog(char*);
char * getLog(void);

<util.c>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <errno.h>
#include "util.h"
#include "sender.h"

//#define DEBUG 1

FILE *log;
static key_t key=0;
static int semid, shmid;
static struct sembuf mem_lock[2]={
0,0,0,
0,1,0
};
static struct sembuf mem_unlock[1]={
0,-1,0
};

void clearLog(int t) {
long *invalid;
if(semop(semid,&mem_lock[0],2)<0) {
#ifdef DEBUG
perror("Can't wait semafor in clearLog");
#endif
}
fclose(log);
remove(LOGFILE);
// clearing long variable
if((invalid=(long*)shmat(shmid,0,0))<0){
#ifdef DEBUG
perror("Error while shmat");
#endif
return;
}
#ifdef DEBUG
fprintf(stderr, "shared mem attached\n");
#endif
*invalid=0;
if(shmdt(invalid)<0) {
#ifdef DEBUG
perror("Can't shmdt");
#endif
return;
}
// cleared
if(t) createLog(NULL);
/* if(semctl(semid,0,IPC_RMID)<0)
perror("Can't delete semafor");
*/
if(semop(semid,&mem_unlock[0],1)<0){
#ifdef DEBUG
perror("Can't unlock semafor in clearLog");
#endif
}
}

int addLog(char *s, int increment){
long *invalid;
#ifdef DEBUG
fprintf(stderr, "semid=%i\n",semid);
#endif
if(semop(semid,&mem_lock[0],2)<0) {
#ifdef DEBUG
perror("Can't wait semafor in addLog");
#endif
return -1;
}
fprintf(log,s);
#ifdef DEBUG
fprintf(stderr,"adding log: %s\n",s);
#endif

if((invalid=(long*)shmat(shmid,0,0))<0){
#ifdef DEBUG
perror("Error while shmat");
#endif
return -1;
}
#ifdef DEBUG
fprintf(stderr, "shared mem attached\n");
#endif
*invalid+=increment;
#ifdef DEBUG
fprintf(stderr, "Now invalid=%ld\n", *invalid);
#endif
if(shmdt(invalid)<0) {
#ifdef DEBUG
perror("Can't shmdt");
#endif
return -1;
}
if(semop(semid,&mem_unlock[0],1)<0) {
#ifdef DEBUG
perror("Can't unlock semafor in addLog");
#endif
return -1;
}
return 0;
}

int createLog(char *s){
long *invalid;

log=fopen(LOGFILE,"wt");
if(!log) return -1;
if(!s && key) return 0;
#ifdef DEBUG
fprintf(stderr,"Creating key \n");
#endif
if((key=ftok(LOGFILE,'A'))<0) {
#ifdef DEBUG
perror("Error while ftok");
#endif
return -1;
}
#ifdef DEBUG
fprintf(stderr,"Creating semafor \n");
#endif
if((semid=semget(key,1,PERM))<0) {
#ifdef DEBUG
perror("Error while semget existing");
#endif
if((semid=semget(key,1,PERM|IPC_CREAT))<0) {
#ifdef DEBUG
perror("Error while semget creating");
#endif
return -1;
}
}
#ifdef DEBUG
fprintf(stderr,"Created semafor, semid=%i\n", semid);
#endif
if((shmid=shmget(key,sizeof(long),PERM ))<0) { //PERM |IPC_CREAT
#ifdef DEBUG
perror("Error while shmget existing in createLog");
#endif
if((shmid=shmget(key,sizeof(long),PERM |IPC_CREAT))<0) { //PERM |IPC_CREAT
#ifdef DEBUG
perror("Error while shmget new in createLog");
#endif
return -1;
}
}
#ifdef DEBUG
fprintf(stderr, "Shared memory got\n");
#endif
if((invalid=(long*)shmat(shmid,0,0))<0){
#ifdef DEBUG
perror("Error while shmat");
#endif
return -1;
}
#ifdef DEBUG
fprintf(stderr, "shared mem attached\n");
#endif
*invalid=0;

#ifdef DEBUG
fprintf(stderr, "invalid cleared: %ld\n", *invalid);
#endif
if(shmdt(invalid)<0) {
#ifdef DEBUG
perror("Can't shmdt");
#endif
return -1;
}
#ifdef DEBUG
fprintf(stderr, "all done\n");
#endif
return 0;
}
char *getLog() {
char *s;
int fd;
long *invalid;
struct stat filestat;

if(semop(semid,&mem_lock[0],2)<0) {
#ifdef DEBUG
perror("Can't wait semafor in getLog");
#endif
return NULL;
}
freopen(LOGFILE,"rt",log);
fd=fileno(log);
fstat(fd,&filestat);
s=(char*)malloc(filestat.st_size+80);
if(!s) return NULL;
fread(s,filestat.st_size,1,log);
s[filestat.st_size]=0;
if((invalid=(long*)shmat(shmid,0,0))<0){
#ifdef DEBUG
perror("Error while shmat");
#endif
return s; // can't get long, but got log !
}
#ifdef DEBUG
fprintf(stderr, "shared mem attached\n");
fprintf(stderr,"Invalid emails: %ld\n",*invalid);
#endif
sprintf(&(s[filestat.st_size]),"Invalid emails: %ld\n",*invalid);
if(shmdt(invalid)<0) {
#ifdef DEBUG
perror("Can't shmdt");
#endif
}
if(semop(semid,&mem_unlock[0],1)<0) {
#ifdef DEBUG
perror("Can't unlock semafor in getLog");
#endif
}
return s;
}
/*int main(int argc, char** argv) {
createLog(argv[0]);
addLog("sdgwegwewgew\n", 1);
addLog("he he he\n", 2);
fprintf(stderr,"\ncurrent log: %s\n",getLog());
clearLog(1);
addLog("aaa\n", 10);
fprintf(stderr,"\ncurrent log: %s\n",getLog());
}*/

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.