PDA

View Full Version : [C] Lock su singoli byte


Njk00
15-02-2010, 15:36
Salve,
il codice è lungo, ma sinceramente non capisco dov'è l'errore: sembra come se i processi siano eseguiti uno alla volta. Ciò che deve fare il programma è scritto nel commento iniziale.


/*
Il processo padre apre il file e crea 2 processi clone che verificano in parallelo un file.
Il primo clone inizia dal primo byte, procede per numeri di byte crescenti e sostituisce tutti gli eventuali byte uguali a "k" con il byte "A".
Il secondo clone fa la stessa cosa ma inizia dall'ultimo byte del file e procede per numeri di byte decrescenti e sostituisce le k con B.
Non appena uno dei due cloni incontra un byte gia verificato dall'altro clone, termina.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>

#define STACK_SIZE 1024*64

int create_lock(int fd, struct flock* lock, int start);
int clone_fn(void*);

int main(int argc, char** argv)
{
char* stack = malloc(STACK_SIZE);
int* param = malloc(sizeof(int) * 2);
int* pid = malloc(sizeof(int) * 2);
int fd = open("/home/nicola/Desktop/test_read.txt", O_RDWR, S_IRUSR|S_IWUSR);

param[0] = 1;
param[1] = fd;
pid[0] = clone(&clone_fn, stack + STACK_SIZE, CLONE_VM|CLONE_SIGHAND, (void*) param);

param[0] = -1;
param[1] = fd;
pid[1] = clone(&clone_fn, stack + STACK_SIZE, CLONE_VM|CLONE_SIGHAND, (void*) param);

sleep(10);

printf("(GOD) Killing clone with pid %d...\n", pid[0]);
int res = kill(pid[0], SIGTERM);
if(res == 0)
printf("(GOD) Clone with pid %d SUCCESSFULL killed\n", pid[0]);
else
{
printf("(GOD) Clone with pid %d NOT killed\n", pid[0]);
perror("kill");
}

printf("(GOD) Killing clone with pid %d...\n", pid[1]);
res = kill(pid[1], SIGTERM);
if(res == 0)
printf("(GOD) Clone with pid %d SUCCESSFULL killed\n", pid[1]);
else
{
printf("(GOD) Clone with pid %d NOT killed\n", pid[1]);
perror("kill");
}

close(fd);
return 0;
}

int unlock(int fd, struct flock* lock, int start)
{
int cmd = F_SETLK;
lock->l_type = F_UNLCK;
lock->l_whence = SEEK_SET;
lock->l_start = start;
lock->l_len = 1;

int res = fcntl(fd, cmd, lock);

if(res == -1)
{
perror("fcntl");
return -1;
}
if(res == 0)
{
int pid = getpid();
printf("(CLONE %d) UNLOCK successfull\n", pid);
return 0;
}
}

int create_lock(int fd, struct flock* lock, int start)
{
int cmd = F_SETLK;
lock->l_type = F_WRLCK;
lock->l_whence = SEEK_SET;
lock->l_start = start;
lock->l_len = 1;

int res = fcntl(fd, cmd, lock);

if(res == -1)
{
perror("fcntl");
return -1;
}
if(res == 0)
{
int pid = getpid();
printf("(CLONE %d) LOCK ACQUIRED!!!\n", pid);
return 0;
}
}

int clone_fn(void* arg)
{
int res;
int pid = getpid();

int* param = malloc(sizeof(int) * 2);
param = (int*) arg;
int id = param[0];
int fd = param[1];

char* buffer = malloc(sizeof(char));
struct flock* lock = malloc(sizeof(struct flock));
int index;
int size = lseek(fd, 0, SEEK_END);

if(id == 1)
{
index = 0;

while(index <= size - 2)
{
res = create_lock(fd, lock, index);

if(res == -1)
{
printf("(CLONE %d) Byte busy, closing...\n", pid);
return 0;
}

else
{
lseek(fd, index, SEEK_SET);
read(fd, buffer, 1);

if(*buffer == 'k')
{
int pos = lseek(fd, index, SEEK_SET);
*buffer = 'A';
write(fd, buffer, 1);
printf("(CHILD %d) writting A in pos %d\n", pid, pos);
}

res = unlock(fd, lock, index);
if(res == -1)
{
printf("(CLONE %d) ERRON in UNLOCK function. Quitting...\n", pid);
return 0;
}

index++;
}
}
}
else
{
printf("-----------------------------CLONE 2 ACTIVE--------------------------\n");
index = size - 2;

while(index >= 0)
{
res = create_lock(fd, lock, index);

if(res != 0)
{
printf("(CLONE %d) Byte busy, closing...\n", pid);
return 0;
}

else
{
lseek(fd, index, SEEK_SET);
read(fd, buffer, 1);

if(*buffer == 'k')
{
int pos = lseek(fd, index, SEEK_SET);
*buffer = 'B';
write(fd, buffer, 1);
printf("(CHILD %d) writting B in pos %d\n", pid, pos);
}

res = unlock(fd, lock, index);
if(res == -1)
{
printf("(CLONE %d) ERRON in UNLOCK function. Quitting...\n", pid);
return 0;
}

index--;
}
}
}

return 0;
}

Grazie a tutti per l'infinita pazienza.