Thread: seeking for exercises

  1. #1
    Registered User
    Join Date
    Oct 2007
    Posts
    100

    seeking for exercises

    Hello there!
    While there is a lot of material for ANSI C, including exercises, it's quite difficult to find exercises where one can practice with linux system calls... Do you know any collection of exercises which could help to practice with the following system calls?

    Thanks so much! bye!
    Code:
    PROCESSES
    fork()			 
    clone()
    sleep()
    usleep()
    sched_yield()
    getpid()
    getuid()
    getgid()
    iopl()
    gettimeofday()
    _exit()
    
    FILE
    open()
    close()
    lseek()
    lstat()
    read()
    write()
    unlink()
    opendir()
    readdir()
    closedir()
    mmap()
    munmap()
    
    
    SIGNALS/SYNCRONIZATION
    alarm()
    sigaction()
    signal()
    kill()
    wait()
    waitpid()
    pause()
    pipe()
    
    LINKING
    dlopen()
    execve()
    system()

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Why don't you just look the commands up in "the official" GNU C Library Reference Manual (most but not all of them are there) and try to apply them practically? This can be quite an exercise in itself, esp. since it contains few real examples.

    In fact, I'll give you an exercise right now: show me a short program using mmap (sec. 13.7)

    ps. You can use TkCodex while you're doing this (see below).
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Oct 2007
    Posts
    100
    Quote Originally Posted by MK27 View Post
    Why don't you just look the commands up in "the official" GNU C Library Reference Manual (most but not all of them are there) and try to apply them practically? This can be quite an exercise in itself, esp. since it contains few real examples.

    In fact, I'll give you an exercise right now: show me a short program using mmap (sec. 13.7)

    ps. You can use TkCodex while you're doing this (see below).
    thanks for your advice, tomorrow (now here in italy it's 21.30!) i'll try to make an exercise with mmap and post it!
    the real problem is that my professor (D.P. Bovet, author of "Understanding the linux kernel") "likes" really a lot the clone() system call, which is the least documented online...
    c u!

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Talking

    Quote Originally Posted by smoking81 View Post
    thanks for your advice, tomorrow (now here in italy it's 21.30!) i'll try to make an exercise with mmap and post it!
    i'll show you mine if you show me yours!
    arrivederci...
    Last edited by MK27; 09-13-2008 at 04:25 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Oct 2007
    Posts
    100
    Quote Originally Posted by MK27 View Post
    i'll show you mine if you show me yours!
    ciao...
    Hello! In the end i preferred to start with an exercise concerning clones and signals since this is the kind of exercise my professor best likes...
    I invented on my own and tried to solve it in the longest way (e.g. i used waitpid when it was not necessary).

    the text of the exercise is:
    Code:
    /*
    *	A process (father) creates 2 clones and passes them:
    *	-The file descriptor of a file to be written
    *	-A char to be written repeatedly in the file
    *	-A number representing the time to wait between a write and the successive
    *	-number of chars to be written
    *	-A number representing the timestamp when the clones have been created
    *
    *	Every clone writes then the char and the moment (calculated since its creation) when the write is performed.
    *
    *	The father waits for the clones to terminate for not more than 60 seconds: then, if this is the case, it kills them with a signal. Finally, it prints the file to stdout.
    *	
    */
    Here is my solution:

    Code:
    #include <sys/wait.h> /* waitpid */
    #include <sys/time.h>
    #include <signal.h> /* kill */
    #include <time.h> /* time */
    #include <sched.h> /* sched_yield clone*/
    #include <sys/types.h> /* open waitpid kill*/
    #include <sys/stat.h> /* open */
    #include <unistd.h> /* sleep */
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h> /* errno */
    
    struct arguments{
    	int fd;
    	char ch;
    	int chars;
    	unsigned int sle;
    	long int start;
    };
    
    typedef struct arguments Arguments;
    
    int lock(const char *lockname)
    {
    	while (1)
    	{
    		int fd = open (lockname,O_CREAT|O_RDWR|O_EXCL,0666);
    		//sleep(1);
    		if (fd<0)
    		{
    			if (errno==EEXIST) //Lock is busy
    			{
    				sched_yield();
    			}
    			else
    			{
    				printf("BAD OPEN LOCK\n");
    				return -1;
    			}
    		}
    		else
    		{
    			return fd;
    		}
    	}
    }
    
    int unlock (char *lockname, int fd)
    {
    	int ret=close(fd);
    	if (ret<0)
    		printf("Lock doesn't exist\n");
    	
    	unlink(lockname);
    	return ret;
    }
    
    
    int clone_f(void *args)
    {
    	pid_t pid=getpid();
    
    
    	Arguments *a=(Arguments *)args;
    	printf("HELLO! I'm the clone having pid=%d and i will write %d times the char'%c' into the file having fd=%d.I'll sleep %u secs between successive writes.\n",(int)pid,a->chars,a->ch,a->fd,a->sle);
    
    	int i,fdlock;
    	long int moment;
    	
    	for (i=0;i<a->chars;i++)
    	{
    		if ((fdlock=lock("LOCK"))<0)
    		{	
    			return 1;
    		}
    		moment=time(NULL)-(a->start);
    		if (write(a->fd,&moment,sizeof(long int))!=sizeof(long int))
    		{
    			printf("Problem while writing moment\n");
    			return 1;
    		}
    		if (write(a->fd,&(a->ch),1)!=1)
    		{
    			printf("Problem while writing the char\n");
    			return 1;
    		}
    		printf("[CLONE %d] has written [%ld]%c in file\n",(int)pid,moment,a->ch);
    
    		if (unlock ("LOCK",fdlock)<0)
    			return 1;
    
    		sleep(a->sle);
    	}
    	return 0;
    }
    
    
    int main (void)
    {
    	int fd;
    	//Create the file
    	if ((fd=open("./trial",O_CREAT|O_TRUNC|O_RDWR,0666))==-1)
    	{
    		printf ("BAD FILE OPEN\n");
    		return 1;
    	}
    	printf("FILE HAS FD=%d\n",fd);
    	pid_t cl1,cl2;
    	int stack1[1024],stack2[1024];
    
    	unsigned int sl_t1=2,sl_t2=2;
    	int chars1=20,chars2=50;
    	char c1='a',c2='b';
    	long int start=time(NULL);
    	Arguments arg1={fd,c1,chars1,sl_t1,start}, arg2={fd,c2,chars2,sl_t2,start};
    
    	//Create clones
    	if ( (cl1=clone(clone_f,&stack1[1023],CLONE_VM|CLONE_FILES,&arg1))==-1)
    	{
    		printf("Bad clone 1\n");
    		return 1;
    	} 
    	printf("CLONE 1 has pid %d\n",(int)cl1);
    
    	if ( (cl2=clone(clone_f,&stack2[1023],CLONE_VM|CLONE_FILES,&arg2))==-1)
    	{
    		printf("Bad clone 2\n");
    		return 1;
    	}
    	printf("CLONE 2 has pid %d\n",(int)cl2);
    	//Wait clones for maximum 60 sec
    	int tokill[2]={1,1}; //set both the clones to be killed explicitly
    	pid_t pid;
    	int i;
    	for (i=0;i<60;i++)
    	{
    		pid=waitpid(-1,NULL,WNOHANG|__WCLONE);
    		if (pid>0) //One clone terminated
    		{
    			if (pid==cl1) 
    			{
    				tokill[0]=0;//First clone terminated 
    				printf("clone 1 has finished\n");
    			}
    			else 
    			{
    				tokill[1]=0;//Second clone term.
    				printf("clone 2 has finished\n");
    			}
    		}
    		sleep(1);
    	}
    	/*
    		********** other possibility: just sleep(60) and then kill(pid,SIGKILL) in any case
    	*/
    	if (tokill[0]==1) { kill(cl1,SIGKILL); printf("clone 1 has been killed\n");}
    	if (tokill[1]==1) { kill(cl2,SIGKILL); printf("clone 1 has been killed\n");}
    	// print file
    	lseek(fd,0,SEEK_SET);
    	long int t; char ch;
    	while (read(fd,&t,sizeof(long int))==sizeof(long int))
    	{
    		if (read(fd,&ch,1)==1)
    			printf("[%ld]%c\n",t,ch);
    		else
    		{
    			printf("unexpected end of file\n");
    			return 1;
    		}
    	}
    	printf("ENDING..\n");
    	close(fd);
    	return 0;
    }
    As you can see, I implemented lock() and unlock() on my own, following an example by my professor. I commented the sleep(1) in the lock which I found in the example, since i didn't understand its need.. Furthermore, I thought (and running the program including this sleep confirmed this) that it could cause a bad synchronization in the writes..
    For what concerns the use of waitpid (beside the fact that it's redundant), this solution seems to work.. But I guessed that it works just because everything happens in timeshots which are multiples of 1, isn't it? I wonder what could happen if a clone ends at time t=0.5 and the father wakes up at time t=1.. would this still work?

    Every comment about this program is more than welcome!

    thank you very much! Bye!

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    mmap()

    Well this is good, because after I did the following I was going to attempt clone but couldn't see what made it so different from fork (except that file descriptors are passed). Of course, most of the man page went over my head...but now I have something concrete to deal with. Thanks, smoking81.

    Anyway, I choose mmap pretty much at random off your list and I'm glad, because it's a pretty clever function. Although my example doesn't do much, I think the syntax and "use value"* should be clear.

    *to me: that I can now create and edit a file in place using a simple char buffer, which beats using fseek or getline if there's information you want saved from one invocation to another. It would also work great in place of a fifo for "interprocess communication" stuff; since it doesn't "drain out" with each read, all the data is maintained and could be read multiple times by more than two seperate programs (and only one need do the map, then just pass the starting address...altho I haven't tried this)


    Code:
    #include <stdio.h>   	// printf
    #include <fcntl.h>	// open, close
    #include <sys/mman.h>	// mmap
    
    int main () {
    	char buffer[4096], *map, messg[]="\nciao mondo\n";
    	const char file[]="/tmp/maptest";
    	int FD=open(file,O_RDWR|O_CREAT);
    	short int i, retv;
    
    	write(FD,buffer,4096);
    	map=mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_SHARED,FD,0);
    	close(FD);	 
    	for (i=0;i<4096;i++) map[i]=54;
    	for (i=0;i<3;i++) putchar(map[66+1]);
    	i=0;
    	while (messg[i] != 0) {map[i+2112] = messg[i]; i++;}
    	i=2112;
    	while (map[i] != 54) {putchar(map[i]); i++;}
    	i=4096;
    	while (map[i] != 0) {putchar(map[i]); i++;}   // hmmm...
     	if ((munmap(map,4096)) != 0) perror("!mumap failed");
    
    	//this now segfaults, so the mmap must really be gone: 
    	//for (i=0;i<3;i++) putchar(map[66+1]);
    }
    I had a text viewer set to "watch" /tmp/maptest at 5 second intervals and it seemed to be updated immediately on disk.

    ps. the line commented "hmm..." produces this:

    Code:
      ELF
    and is actually 32 bytes long, I think.

    pps. how much do does it cost to go to school in Italy?
    Last edited by MK27; 09-13-2008 at 07:54 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Registered User
    Join Date
    Oct 2007
    Posts
    100
    Quote Originally Posted by MK27 View Post

    pps. how much do does it cost to go to school in Italy?
    i go to the university (and hope to finish it soon)! :-)
    anyway, public schools are for free, public university can cost from 0 to 1200€ per year according to your income, private schools and univ are of course more expensive, but not always are better than public ones (above all the universities!) and are 99% of the time managed by priests/nuns..

    bye

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Exclamation

    I just noticed

    Code:
    for (i=0;i<3;i++) putchar(map[66+1]);
    should really have been

    Code:
    for (i=0;i<3;i++) putchar(map[66+i]);
    which would produce the same output.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Filestream Not Seeking to the Beginning
    By pobri19 in forum C++ Programming
    Replies: 2
    Last Post: 04-11-2009, 03:59 AM
  2. Seeking some clarifications on these codes.
    By Dontgiveup in forum C++ Programming
    Replies: 3
    Last Post: 04-02-2009, 07:20 PM
  3. Aeres seeking interested hoobyists!
    By Akkernight in forum Projects and Job Recruitment
    Replies: 13
    Last Post: 03-19-2009, 11:50 AM
  4. Seeking Head Coder for MUD Partnership
    By Draconar in forum Projects and Job Recruitment
    Replies: 0
    Last Post: 06-25-2006, 04:05 PM