Hello everybody!
Today I wanted to solve this exercise:
Here is my solution:Code:A main process opens a file (filled with bytes in the range 0-255) and then creates 2
clone processes which have to parse (of course in parallel) the file starting respectively from
the beginning and the end of the file: their task is to replace every byte==255 with the value 0.
A process returns as it meets a byte already processed by the other clone.
as you can see, i implemented my lock and unlock functions, the only problem I found is that if i replace the usleep(200) with a sched_yield or a shorter time for sleeping the 1st process will win all the contents on the lock and arrive at the end of the file before the second can start its job... Can you please explain me the reason for this?Code:#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sched.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <wait.h>
int fd, indexA, indexB;
struct args{
int *index;
int incdec;
};
typedef struct args Args;
int lock(char *filename)
{
int fd;
while (1)
{
fd=open(filename,O_CREAT|O_EXCL|O_RDWR|O_TRUNC,0666);
if (fd<0&&errno!=EEXIST)
{
printf("BAD LOCK OPEN\n");
return 0;
}
if (fd<0&&errno==EEXIST)
{
sched_yield();
}
else
break;
}
return fd;
}
int unlock (char *filename, int fd)
{
if (close(fd)<0)
{
printf("BAD LOCK CLOSE\n");
return 0;
}
if (unlink(filename)<0)
{
printf ("BAD UNLINK\n");
return 0;
}
usleep(200);// SCHED_YIELD won't work!
return 1;
}
int cloneA(void* args)
{
Args *a=(Args *)args;
printf("PID %d: index: %d incdec: %d\n",(int)getpid(),*(a->index),a->incdec);
int lockfd;unsigned char ch;
sleep(1);
while (indexA<=indexB)
{
lockfd=lock("LOCKFILE");
lseek(fd,*(a->index),SEEK_SET);
read(fd,&ch,sizeof(unsigned char));
printf("%d index: %d CH:%d\n",(int )getpid(),*(a->index),ch);
if (ch==255)
{
printf("%d has found a char == 255 in position %d\n",(int)getpid(),*(a->index));
lseek(fd,*(a->index),SEEK_SET);ch=0;
write(fd,&ch,sizeof(unsigned char));
}
*(a->index)+=a->incdec;
unlock("LOCKFILE",lockfd);
}
return 0;
}
void fillfile(int fd, int numbytes)
{
int i;
srand(time(NULL));
unsigned char ch;
lseek (fd,0,SEEK_SET);
for (i=0;i<numbytes;i++)
{
ch=rand()%256;
write(fd,&ch,sizeof(unsigned char));
}
}
void printfilenums(int fd)
{
lseek(fd,0,SEEK_SET);
unsigned char ch;
while ((read(fd,&ch,sizeof(unsigned char)))==sizeof(unsigned char))
{
printf("%d ",ch);
}
printf("\n\n");
}
int main(int argc, char * argv[])
{
if (argc!=2)
{
printf("USAGE: program infile\n");
return 1;
}
fd=open (argv[1],O_TRUNC|O_RDWR);
fillfile(fd,70);
printfilenums(fd);
indexA=lseek(fd,0,SEEK_SET);
indexB=lseek(fd,-1,SEEK_END);
printf("\nIndex A=%d Index B=%d\n",indexA,indexB);
int stackA[1024],stackB[1024];
pid_t pidA,pidB;
Args a={&indexA,1};
Args b={&indexB,-1};
pidA=clone(cloneA,&stackA[1023],CLONE_VM|CLONE_FILES,&a);
if (pidA<0) {printf("BAD CLONE A\n");return 1;}
pidB=clone(cloneA,&stackB[1023],CLONE_VM|CLONE_FILES,&b);
if (pidB<0) {printf("BAD CLONE B\n");return 1;}
pid_t pid=waitpid(-1,NULL,__WCLONE);
printf("%d terminated\n",(int)pid);
pid=waitpid(-1,NULL,__WCLONE);
printf("%d terminated\n",(int)pid);
printfilenums(fd);
close(fd);
return 0;
}
Thanks a lot! bye!