Linux Internals Programming Examples | Sample Programs for Beginners

HomeLinux Internals | Course HomeLinux Internals | Sample Programs

Linux Internals and TCP/IP Networking- Sample Programs

Linux Internals Programming Examples is the first step you take to transition from theory to practical. These sample programs for beginners typically demonstrated in a classroom will ensure you are able to immediately see it running in front of your eyes. Added to that our mentors will provide you some exercises where you will be modifying the code in the class itself. 

Chapter1 : Transition from C to Linux programmer

Brief:

Learn C library usage, understand difference between library functions and user defined functions with example of square root calculation. This Linux Internals Programming Examples will start your transition from a C programmer to an Embedded Programmer.

Source Code:

   
/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://emertxe-group.com) 
 *   Date           : Tue 16 Feb 2016 17:05:14 IST
 *   File           : t001.c
 *   Title          : Library usage in C - Square root 
 *   Description    : Understand difference between library functions and user
 *  		      defined functions with example of square root calculation
 *
 *----------------------------------------------------------------------------*/

#include 
#include 
#include 
float mysqrt(int num);
int main()
{
	int num;
	printf("Enter the number to find square rootn");
	scanf("%d", &num);
	float res = mysqrt(num);
	printf("Square root of %d is %f n", num, res);
	printf("Sqrt output is       %f n", sqrt(num));
}
float mysqrt(int num)
{
	int count = 10;
	float guess = 30;

	while(count--)
	{
		guess = guess - (fabsf(guess * guess - num) / (2 * guess));
	}
	return fabsf(guess);
}

Example Output: 

Linux Internals Programming Examples - 1

Brief:

To understand various segments of a running program, it is important to know the working of storage classes in C. This program demonstrates extern variable usage by accessing a global variable from another file. This Linux Internals Programming Examples will start your transition from a C programmer to an Embedded Programmer.

 

Source Code:

 

li_t002_1_ch1_osbasics_storage_classes_usage.c

>------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 16 Feb 2016 17:11:00 IST
 *   File           : li_t002_1_ch1_osbasics_storage_classes_usage.c
 *   Title          : Extern variable usage in C 
 *   Description    : To understand various segements of a running program,it 
 *                    is important to know the working of storage classes in C.
 *                    This program demonstrates extern variable usage by 
 *                    accessing a global variable from another file.
 *   Usage          : Compile t002_2.c along with this 
 *
 *----------------------------------------------------------------------------*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int fun(void);
int global;
int main()
{
	/* default value of global variable */
	printf("global = %dn", global);
	global = 10;
	/* call a function defined in another c file*/
	fun();
	/* Check again the value after function call*/
	printf("global = %dn", global);
}

 

 li_t002_2_ch1_osbasics_storage_classes_usage.c
/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 16 Feb 2016 17:16:44 IST
 *   File           : li_t002_2_ch1_osbasics_storage_classes_usage.c
 *   Title          : Extern variable usage in C 
 *   Description    : To understand various segements of a running program,it 
 *                    is important to know the working of storage classes in C.
 *                    This program demonstrates extern variable usage by 
 *                    accessing a global variable from another file.
 *   Usage          : Compile t001_2.c along with this 
 *
 *----------------------------------------------------------------------------*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int global;
int fun(void)
{

	/* Check again the value in function */
	printf("global = %dn", global);
	/* Changing value inside function */
	global = 20;
}

Example output:

Linux Internals Programming Examples - 2

Chapter2 : System calls usage in Linux

Brief:

System calls in Linux provide unified access to resources that Kernel is managing. This first program introduces a beginner to timer related system calls by getting time of the day and printing all related information.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 16 Feb 2016 16:27:07 IST
 *   File           : li_t003_ch2_syscalls_timer.c
 *   Title          : System calls usage in Linux - Timer 
 *   Description    : System calls in Linux provide unified access to resources
 *                    that Kernel is managing. This first program introduces 
 *                    a beginner to timer related system calls by getting time
 *                    of the day and printing all related information. 
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <time.h>	
#include <string.h>
int main()
{

	/* This structure has EPOC time in seconds and microseconds */
	struct timeval tv;
	/* This structure holds time in broke down time format */
	struct tm *cur_time;

	/* Store current seconds and microseconds in structure */
	gettimeofday(&tv, NULL);
	/* To convert seconds to broke down time */
	cur_time = localtime(&tv.tv_sec);
	/* TODO print this seconds and compare with `date +%s`*/

	/* Printing hours minitues and seconds */
	printf("%d:%d:%dn", cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec);
	/*TODO print all values from structure by refering man page */

}

Example Output: 

Linux Internals Programming Examples - 3
Brief:

System calls in Linux provide unified access to resources that Kernel is managing. This is second level program for performing file operations using system calls. Using this example, developers can also understand Virtual File System (VFS) in Linux.

  Source Code:
/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 16 Feb 2016 16:49:51 IST
 *   File           : li_t004_ch2_syscalls_file.c
 *   Title          : System calls usage in Linux - File operations
 *   Description    : System calls in Linux provide unified access to resources
 *                    that Kernel is managing. This is second level program 
 *                    for performing file operations using system calls. Using 
 *                    this example, developers can also understand Virtual File
 *                    System (VFS) in Linux.  
 *
 *----------------------------------------------------------------------------*/

#include <sys/types.h>
#include <sys/stat.h>
#include 
#include 
#include <sys/mman.h>
#include 
#include 
#include 

#define MAX 10

int main(int argc, char **argv)
{
	/* For storing file discriptor */
	int source_fd;
	int rd_ret, wt_ret;
	/* Buffer to store read values */
	char buff[10];

	/* Open file in read-only mode */
	source_fd = open(argv[1], O_RDONLY);
	/* Checks for error */
	if (source_fd == -1)
	{
		perror("open");
		return (1);
	}
	do {
		/* reading MAX bytes from file */
		rd_ret = read(source_fd, buff, MAX);
		/* Checks for error */
		if (rd_ret == -1)
		{
			perror("read");
			return 2;
		}
		/* writing to stdout */
		wt_ret = write(1, buff, rd_ret);
		/* Checks for error */
		if (wt_ret == -1)
		{
			perror("write");
			return 3;
		}
		/* Loops till end-of-files */
	}while(rd_ret != 0);
}
sample_file.txt
/*------------------------------------------------------------------------------ 
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 16 Feb 2016 16:49:51 IST
 *   File           : li_t004_ch2_syscalls_file.c
 *   Title          : System calls usage in Linux - File operations
 *   Description    : System calls in Linux provide unified access to resources
 *                    that Kernel is managing. This is second level program 
 *                    for performing file operations using system calls. Using 
 *                    this example, developers can also understand Virtual File
 *                    System (VFS) in Linux.  
 *----------------------------------------------------------------------------*/
Example output:
Linux Internals Programming Examples - 4

Chapter3 : Creating process in Linux

Brief:

A running instance of a program is called as Process in any OS. In Linux to create a new process there are multiple system calls are provided. System() is one of them, which is demonstrated with an example below. This Linux Internals Programming Examples is the first feel of creating multi-tasking in Linux.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:00:04 IST
 *   File           : li_t005_ch3_process_system.c
 *   Title          : Creating a new process in Linux - System 
 *   Description    : A running instance of a program is called as Process in 
 *                    any OS. In Linux to create a new process there are multiple
 *                    system calls are provided. System() is one of them, which 
 *                    is demonstrated with an example below. 
 *----------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main()
{
	printf("Running top with systemn");
	/* TODO try other commands like ps, sleep, top rtc and observe the behaviour */
	system("ls -l");
	printf("Done.n");
	exit(0);
}

Example output:

Linux Internals Programming Examples - 5

Brief:

A running instance of a program is called as Process in any OS. In Linux to create a new process there are multiple system calls are provided. fork() is one of them. When fork is used, a process creates a copy of itself. It is usually a implemented in the kernel. Here, fork system call is demonstrated with an example below. If fork is successful, then there will be two processes. One will be a parent process and other will be a child process.  Both will execute the main function from the point where fork has returned.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:03:15 IST
 *   File           : li_t006_ch3_process_fork.c
 *   Title          : Creating a new process in Linux - fork()
 *   Description    : A running instance of a program is called as Process in 
 *                    any OS. In Linux to create a new process there are multiple
 *                    system calls are provided. fork() is one of them, which 
 *                    is demonstrated with an example below. 
 *----------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

int main ()
{
	printf("Fork Demonstrationn");
	fork();
	printf("nHello Worldn");
	return 0;
}

Example output:

Linux Internals Programming Examples - 6
 

Brief:

Using (fork()) fork system call in Linux, multiple processes can be created by calling the same system call in sequence. This is an example code to demonstrate multiple child creation and build clear understanding of parent & child mechanism in Linux. If fork is successful, then there will be two processes. One will be a parent process and other will be a child process. Both will execute the main function from the point where fork has returned. This is repeated for all 3 fork() while invoked. This Linux Internals Programming Examples is a classic multitasking scenario where you go beyond C programming.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:15:45 IST
 *   File           : li_t007_ch3_process_multiple_fork.c
 *   Title          : Creating multiple processes using fork()
 *   Description    : Using fork() multiple processes can be created by calling
 *                    the same system call in sequence. This is an example code
 *                    to demonstrate multiple child creation and build clear 
 *                    understanding of parent & child mechanism in Linux  
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main ()
{
	printf("Fork Demonstrationn");
	fork();
	fork();
	fork();
	printf("Hello Worldn");
	return 0;
}

Example output:

Linux Internals Programming Examples - 7

Brief:

When new process is created in Linux, a corresponding data base entry is made by the Kernel. Commonly known as Task Control Block (TCB)/Process Control Block (PCB),it maintains all critical information about the process. To differentiate between a parent and child PID is used. The following program demonstrates the how to get the process id in UNIX / LINUX.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:05:06 IST
 *   File           : li_t008_ch3_process_pid_ppid.c
 *   Title          : Accessing PID and PPID information of process 
 *   Description    : When new process is created in Linux, a corresponding 
 *                    data base entry is made by the Kernel.Commonly known as 
 *                    Task Control Block (TCB)/Process Control Block (PCB),it  
 *                    maintains all critical information about the process. To
 *                    differentiate between a parent and child PID is used. The 
 *                    folowing program demonstrates the same.  
 *----------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main()
{
	pid_t child_pid;

	printf("The main program process ID is %dn", (int)getpid());

	/* fork returns new child process id to parent and 0 to child */
	child_pid = fork();
        /* If its > 0 its parent process */ 	
	if (child_pid > 0)
	{
		printf("This is the parent process,with id %dn", (int)getpid());
		printf("The child’s process ID is %dn", (int)child_pid);
	}
	/* If its zero then its child process */
	else if (child_pid == 0) 
	{
		printf ("This is the child process, with id %dn", (int)getpid());
	}
	else
	{
		perror("fork");
	}
	return 0;
}

Example output:

Linux Internals Programming Examples - 8

Brief:

Upon creating new process, parent/child will have their own copy of code & data. Following program demonstrates the same by building the core concept of multi-tasking. It also introduced wait() system call. Learn how to create multiple process using fork() here.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t009_ch3_process_variable_usage.c
 *   Title          : Accessing variables between multiple processes - fork()
 *   Description    : Upon creating new process,parent/child will have their
 *                    own copy of code & data.Following program demonstrates
 *                    the same by building the core concept of multi-tasking.It
 *                    also introduced wait() system call.  
 *----------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main()
{
	pid_t pid;
	char *message;
	int count;
	int exit_code;

	printf("fork program startingn");
	pid = fork();
	switch(pid) 
	{
		case -1:
			perror("fork");
			exit(1);
		case 0:
			message = "This is the child";
			count = 5;
			/* TODO try different values here and chech the behaviour */
			exit_code = 37;
			break;
		default:
			message = "This is the parent";
			count = 3;
			exit_code = 0;
			break;
	}

	/* Which process will execute this part ? parent, child or both.*/
	for(; count > 0; count--) 
	{
		puts(message);
		sleep(1);
	}

	/*  This section of the program waits for the child process to finish.  */
	if(pid) 
	{
		int stat_val;
		pid_t child_pid;

		child_pid = wait(&stat_val);

		printf("Child has finished: PID = %dn", child_pid);
		if(WIFEXITED(stat_val))
		{
			/* Normal termination */
			printf("Child exited with code %dn", WEXITSTATUS(stat_val));
		}
		else
		{
			/* Abnormal termination */
			printf("Child terminated abnormallyn");
		}
	}
	exit(exit_code);
}

Example output:

Linux Internals Programming Examples - 9

Brief:

Along with fork() and system(), the exec() system call is another way to create a new process. Unlike the previous exec() works differently by replacing existing process. To understand better, exec system call example program is given below. Know syntax for some of exec family of functions below before getting into the program explained. This Linux Internals Programming Examples give you various options provided in Linux for creating a new process.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t011_1_ch3_process_exec.c
 *   Title          : Creating new process - exec() system call 
 *   Description    : Along with fork() and system(), the exec() system call is
 *                    another way to create a new process. Unlike the previous 
 *                    exec() works differently by replacing existing process. 
 *----------------------------------------------------------------------------*/
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>

int main()
{
	int num;
	char strng[10];

	printf("Before exec my ID is %dn", getpid());
	printf("My Parent process's id is %dn", getppid());

	printf("Enter a numbern");
	scanf("%d", &num);
	/* Converting integer to string */
	sprintf(strng, "%d", num);
	printf("exec startsn");
   	/*Replace <PATH> by current Path in which ex2 is there*/
	execl("<path>/ex2","ex2", strng, (char *)0);
	printf("this won't printn");
	return 0;
}

Example output:

Linux Internals Programming Examples - 10

Chapter 4 : IPC Mechanisms

Brief:

IPC mechanisms provide various ways and means to share information between multiple processes. Creating pipes in Linux is the simplest way to communicate between parent and child in a uni-directional way.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t013_ch4_ipc_pipe.c
 *   Title          : IPC mechanism - Usage of pipe 
 *   Description    : IPC mechanisms provide various ways and means to share 
 *                    information between multiple processes.Creating pipe is
 *                    the simplest way to communicate between parent and child
 *                    in a uni-directional way. 
 *
 *----------------------------------------------------------------------------*/

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>

int main()
{
	int fds[2];
	pid_t pid;
	int num;

	/* Create a pipe here, its important to do before fork */
	pipe(fds);

	pid = fork();

	if(pid == 0)
	{
		printf("Inside child process...n");
		printf("Enter the integer you want to share with parentn");
		scanf("%d",&num);

		/* Write into the pipe for the parent to read */
		write(fds[1],&num,sizeof(num));

		/*
		 * TODO: Try out the following 
		 *       1. The value of 'num' is different in parent & child -- understand 
		 *       2. Exchange a string between parent & child by sending the length first
		 */
	}
	else
	{
		printf("Inslide parent process...n");

		/* Read from the pipe and print the output */
		read(fds[0],&num,sizeof(num));
		printf("Integer received from parent: %dn",num);
	}
	return(0);
}

Example output:

Brief:

IPC mechanisms provide various ways and means to share information between multiple processes. FIFO is one of the simplest and effective way to establish IPC. Here is an example of FIFO creation in linux (receiver).

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t014_ch4_ipc_fifo_receiver.c
 *   Title          : IPC mechanism - Usage of FIFO (Named pipe) - Receiver
 *   Description    : IPC mechanisms provide various ways and means to share 
 *                    information between multiple processes. FIFO is one of the 
 *                    simplest and effective way to establish IPC. Here is an
 *                    example of FIFO (receiver).
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#define FIFO_NAME "/tmp/myfifo"
#define MAX_STRING_LEN 80

int main()
{
	int fd, pp;

	fd = open(FIFO_NAME, O_RDONLY);
	if (fd < 0)
	{
		perror("Open");
		exit(1);
	}
	else
	{
		/* As a unrelated process read from the FIFO and print */
		read(fd,&pp,sizeof(pp));
		printf("FIFO message received: %dn",pp);
		read(fd,&pp,sizeof(pp));
		printf("FIFO message received: %dn",pp);
		close(fd);
		exit(0);
	}
}

 

Example output:

Brief:

IPC mechanisms provide various ways and means to share information between multiple processes. FIFO is one of the simplest and effective way to establish IPC. Here is named pipe example (FIFO sender).

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t014_ch4_ipc_fifo_sender.c
 *   Title          : IPC mechanism - Usage of FIFO (Named pipe) - Sender 
 *   Description    : IPC mechanisms provide various ways and means to share 
 *                    information between multiple processes. FIFO is one of the 
 *                    simplest and effective way to establish IPC. Here is an
 *                    example of FIFO (sender).
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#define FIFO_NAME "/tmp/myfifo"
#define MAX_STRING_LEN 80

int main()
{
	int fd, pp;

	/* Create a pipe */
	mknod(FIFO_NAME,0666,0);

	/* TODO: After opening, check the type by doing ls -al,re-iterate VFS */

	fd = open(FIFO_NAME, O_WRONLY);
	if (fd < 0)
	{
		perror("Open");
		exit(1);
	}
	else
	{
		/* Send some hard coded value between two processes who are not related */
		pp = 100;
		write(fd,&pp,sizeof(pp));
		pp = 200;
		write(fd,&pp,sizeof(pp));
		printf("Value sent to FIFOn");
		close(fd);
		exit(0);
	}
}

 

Example output:

Brief:

IPC mechanisms provide various ways and means to share information between multiple processes. Shared memory offers best performance in terms of speed as it avoids copying data un-necessarily. Here is an example of shared memory (reader) program that reads data.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t015_ch4_ipc_shared_memory_reader.c
 *   Title          : IPC mechanism - Usage of Shared memory - Reader 
 *   Description    : IPC mechanisms provide various ways and means to share 
 *                    information between multiple processes. Shared memory 
 *                    offers best performance in terms of speed as it avoids 
 *                    copying data un-necessarily. Here is an example of shared 
 *                    memory (reader) program that reads data. 
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define SMSIZE 100

int main()
{
    int shmid;
    key_t key;
    int *shm;

    /* Use the same key as in writer */
 	key = 'B';

    /* Get the shared memory, creation is already done */
	shmid = shmget(key,SMSIZE, 0666);

    if (shmid < 0)
    {
    	perror("shmget");
    	exit(1);
    }

	/* Attach to shared memory */
    shm = shmat(shmid,NULL,0);
    if (shm < 0)
    {
    	perror("shmat");
    	exit(0);
    }
    else
    {
		/* Read the value from shared memory and print */
		printf("Value from shared memory: %dn",*shm);
	}
	
	/*
	 * TODO: 1. Detach & remove the shared memory. Confirm deletion by executing ipcs
	 *       2. Extend this program for assignment in order to exhange string
	 */
}

Example output:

Brief:

IPC mechanisms provide various ways and means to share information between multiple processes. Shared memory offers best performance in terms of speed as it avoids copying data un-necessarily. Here is an example of inter process communication using shared memory (writer) program that writes the data.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t015_ch4_ipc_shared_memory_writer.c
 *   Title          : IPC mechanism - Usage of Shared memory - Writer
 *   Description    : IPC mechanisms provide various ways and means to share 
 *                    information between multiple processes. Shared memory 
 *                    offers best performance in terms of speed as it avoids 
 *                    copying data un-necessarily. Here is an example of shared 
 *                    memory (writer) program that writes the data. 
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

/* Define the shared memory size */
#define SMSIZE 100

int main()
{
    int shmid,num;
    int *shm;
    key_t key;

	/* Key can be hardcoded, but use the same in reader & writer */
    key = 'B';


    /* Create a shared memory */
	shmid = shmget(key,SMSIZE,IPC_CREAT | 0666);

    if (shmid < 0)
    {
    	perror("shmget");
    	exit(1);
    }
    else
	{
    	shm = shmat(shmid,NULL,0);
      /*
       * TODO: 1. Execute 'ipcs' command and verify shared memory is created 
       *       2. Take the value from the user which you want to write into shared memory 
       *       3. Perform Shared memory detach by reading the man pages 
      */
    	printf("Enter the numbern");
    	scanf("%d",&num);
     /* This is the reason why shared memory is the fastest form of IPC.
      * You are manipulating the shared memory as if it is a local pointer.
      * This avoids un-necessary copy with Kernel 
    */
		*shm = num;
	}
}

Example output:

Brief:

IPC mechanisms provide various ways and means to share information between multiple processes. Signals in IPC are used mainly to intimate about events in the system and handle them appropriately. This is a simple usage of signal() system call for capturing signals via call-back function.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t016_ch4_ipc_signal_handling.c
 *   Title          : IPC mechanism - Usage of Signals - Simple usage 
 *   Description    : IPC mechanisms provide various ways and means to share 
 *                    information between multiple processes. Signals are used 
 *                    mainly intimate about events in the system and handle them
 *                    appropriately. This is a simple usage of signal() system
 *                    call for capturing signals via call-back function.
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void my_signal_handler1(int signo); 
void my_signal_handler2(int signo); 

int main() 
{
	int mypid;

	/* Registering for SIGUSR1 & SIGUSR2 */

	/* Here my_signal_handler1 & my_signal_handler2 are callback functions */
	if(signal(SIGUSR1,my_signal_handler1) == SIG_ERR)
		printf("Cannot catch this signal-1n");
	if(signal(SIGUSR2,my_signal_handler2) == SIG_ERR)
		printf("Cannot catch this signal-2n");

	
	/* Now wait in a synchronous loop for the signals to arrive */
	while(1)
	{
		printf("Awaiting for signals. My PID is: %dn",getpid());
		sleep(2);
	}

	/*
	 * TODO: 1. Replace the synchronous while(1) loop with pause() 
	 *		 2. Use of raise() and creating self signals
	 */

	printf("Signal handled, I am exitingn");
}
	
/* Signal handler - Asynchronous handling & callback function */
void my_signal_handler1(int signo)
{
	/* These functions are called in the context of the Kernel. So minimal handling */
	if (signo == SIGUSR1)  
		printf("Received SIGUSR1n");
	else	    	
		printf("Error:Sorry, wrong signaln");
}

void my_signal_handler2(int signo)
{
	/* These functions are called in the context of the Kernel. So minimal handling */
	if (signo == SIGUSR2)  
		printf("Received SIGUSR2n");
	else	    	
		printf("Error:Sorry, wrong signaln");
}

Example output:

Terminal 1

 

Terminal 2

Brief:

IPC mechanisms provide various ways and means to share information between multiple processes. Signals can be sent to the process itself, alarm() is one of them. Find sigalrm linux example here. This example demonstrates alarm() usage and how it works.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (http://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t017_ch4_ipc_signal_alarm.c
 *   Title          : IPC mechanism - Usage of signals - Alarms usage 
 *   Description    : IPC mechanisms provide various ways and means to share 
 *                    information between multiple processes. Signals can be 
 *                    sent to the process itself, alarm() is one of them. This
 *                    example demonstrates alarm() usage and how it works. 
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

int main()
{

	/* Raise the ALARM, after 5 seconds */
	printf("Calling ALARM for 5 seconds, YOUR handlern");
	alarm(5);

	/* This loop is required for me to handle when the alarm happens */
	while (1);

	/* After alarm the process will terminate */
	printf("ALARM over...let me wake up nown");

	return 0;
}

Example output:

Brief:

Apart from handling signals after they occur, the default handling mechanism can be changed by using sigaction(). This example demonstrates the same for alarm() signal.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t018_ch4_ipc_signal_advaned_handling.c
 *   Title          : IPC mechanism - Usage of Signals - Advanced handling 
 *   Description    : Apart from handling signals after they occur, the default
 *                    handling mechanism can be changed by using sigaction(). 
 *                    This example demonstrates the same for alarm() signal.
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

struct sigaction new_act, old_act;

void alarm_handler(int not_using)
{
	printf("Alarm occured, inside my handlern");
}

int main()
{

	/* Whenever ALARM comes call my handler, callback function */
	new_act.sa_sigaction = alarm_handler;
	sigaction(SIGALRM, &new_act,NULL);

	/* Raise the ALARM, after 5 seconds */
	printf("Calling ALARM for 5 seconds, YOUR handlern");
	alarm(5);

	/* Lets sleep 1 sec more than the set alarm time to keep the process alive */
	sleep(6); 

	printf("ALARM triggered .. Lets continuen");

	return 0;
}

 

Example output:

Brief:

Apart from handling signals after they occur, the default handling mechanism can be changed by using sigaction(). This example demonstrates the same for SEGV signal.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t019_ch4_ipc_signal_advaned_handling.c
 *   Title          : IPC mechanism - Usage of Signals - Advanced handling 
 *   Description    : Apart from handling signals after they occur, the default
 *                    handling mechanism can be changed by using sigaction(). 
 *                    This example demonstrates the same for SEGV signal.
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <unistd.h>
#include <sys/signal.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>

void handler(int signum, siginfo_t *info, void *dummy)
{
	printf("Signal recieved with %dn", signum);
	printf("Signal send from %dn", info->si_pid);
}


int main()
{
	struct sigaction act, oldact;

	memset(&act, 0, sizeof(act));
	act.sa_sigaction = handler;
	act.sa_flags = SA_SIGINFO;
	sigaction(SIGSEGV, &act, &oldact);

	pause();
	return 0;
}

Example output:

Terminal 1

 

Terminal 2

Chapter 5 : TCP/IP Socket programming

Brief:

Sockets offer interfaces with TCP/IP stack inside Linux. Kernel, using which remote connections can be established over a network. This program demonstrates various steps to establish successful three-way handshake as a client.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t020_ch5_tcp_client.c
 *   Title          : IPC mechanism - Usage of TCP socket - Client 
 *   Description    : Sockets offer interfaces with TCP/IP stack inside Linux 
 *                    Kernel, using which remote connections can be established
 *                    over a network. This program demonstrates various steps
 *                    to establish successful three-way handshake as a client. 
 *
 *----------------------------------------------------------------------------*/
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>

#define SERVER_IP_ADDRESS 	"127.0.0.1"
#define SERVER_PORT       	5000
#define CLIENT_BUFF_SIZE	20

int main()
{
    int sock_fd,c_size;
    char client_buff[CLIENT_BUFF_SIZE];
    struct sockaddr_in serv_addr; 

	/* Create a client socket */
    if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("Error: Could not create socketn");
        return 1;
    } 

	/* Binding with client socket is optional here */

	/* Populate it with server address details */
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERVER_PORT); 
    serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDRESS);

	/* Get the message from client */
	printf("Enter the message you want to sent to server:n");
	fgets(client_buff, CLIENT_BUFF_SIZE, stdin);

     if(connect(sock_fd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) != 0)
     	     printf("Error connecting to servern");
     else
     	     printf("Connection successfuln");

	/* Send the message to server */
	c_size = send(sock_fd, (void *)&client_buff, CLIENT_BUFF_SIZE,0);

	if(c_size)
		printf("Message sent to server successsfully, please checkn");
	else
		printf("Error: Message sendn");
	
	close(sock_fd);
}

Example output:

 

Brief:

Sockets offer interfaces with TCP/IP stack inside Linux. Kernel, using which remote connections can be established over a network. This program demonstrates various steps to establish successful three-way handshake as a server.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t020_ch5_tcp_server.c
 *   Title          : IPC mechanism - Usage of TCP socket - Server
 *   Description    : Sockets offer interfaces with TCP/IP stack inside Linux 
 *                    Kernel, using which remote connections can be established
 *                    over a network. This program demonstrates various steps
 *                    to establish successful three-way handshake as a server. 
 *
 *----------------------------------------------------------------------------*/
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 5000
#define SERVER_LENGTH 10
#define SERVER_BUFF 20

int main()
{

	int sock_fd, data_sock_fd,buffer_len;
    struct sockaddr_in serv_addr; 
	char serv_buffer[SERVER_BUFF];

	printf("Jayakumar: Server is waiting...n");

	/* Create a TCP socket */
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);

	/* Bind it to a particular IP address & port) */
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    serv_addr.sin_port = htons(SERVER_PORT); 

    bind(sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 

	/* Wait and listen for incoming connections */
    listen(sock_fd, SERVER_LENGTH);

   	/* If there are any, accept and create a new data socket */
    data_sock_fd = accept(sock_fd, (struct sockaddr*)NULL, NULL); 

    /* Try to get some actual data from client */
	recv(data_sock_fd, (void *) serv_buffer,SERVER_BUFF,0);

	/* Print the data received from client */
	printf("Here is the client data: %s",serv_buffer);

	/* Close the sockets now */
	close(data_sock_fd);
	close(sock_fd);
}

Example output:

Linux Internals Programming Examples - 20

Brief:

Sockets offer interfaces with TCP/IP stack inside Linux. Kernel, using which remote connections can be established over a network. This program demonstrates various steps to establish successful three-way handshake as a client.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t021_ch5_tcp_concurrent_client.c
 *   Title          : IPC mechanism - Usage of TCP socket - Conrurrent Client 
 *   Description    : Sockets offer interfaces with TCP/IP stack inside Linux 
 *                    Kernel, using which remote connections can be established
 *                    over a network. This program demonstrates various steps
 *                    to establish successful three-way handshake as a client. 
 *
 *----------------------------------------------------------------------------*/
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>

#define SERVER_IP_ADDRESS 	"127.0.0.1"
#define SERVER_PORT       	5000
#define CLIENT_BUFF_SIZE	20

int main()
{
    int sock_fd,c_size;
    char client_buff[CLIENT_BUFF_SIZE];
    struct sockaddr_in serv_addr; 

	/* Create a client socket */
    if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("Error: Could not create socketn");
        return 1;
    } 

	/* Binding with client socket is optional here */

	/* Populate it with server address details */
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERVER_PORT); 
    serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDRESS);

	/* Get the message from client */
	printf("Enter the message you want to sent to server:n");
	fgets(client_buff, CLIENT_BUFF_SIZE, stdin);

     if(connect(sock_fd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) != 0)
     	     printf("Error connecting to servern");
     else
     	     printf("Connection successfuln");

	/* Send the message to server */
	c_size = send(sock_fd, (void *)&client_buff, CLIENT_BUFF_SIZE,0);

	if(c_size)
		printf("Message sent to server successsfully, please checkn");
	else
		printf("Error: Message sendn");
	
	close(sock_fd);
}

Example output:

Linux Internals Programming Examples - 21

Brief:

Sockets offer interfaces with TCP/IP stack inside Linux. Kernel, using which remote connections can be established over a network. This program demonstrates various steps to establish successful three-way handshake as a server and handle multiple clients concurrently.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t021_ch5_tcp_concurrent_server.c
 *   Title          : IPC mechanism - Usage of TCP socket - Conrurrent Serv
 *   Description    : Sockets offer interfaces with TCP/IP stack inside Linux 
 *                    Kernel, using which remote connections can be established
 *                    over a network. This program demonstrates various steps
 *                    to establish successful three-way handshake as a server
 *                    and handle multiple clients concurrently. 
 *
 *----------------------------------------------------------------------------*/

#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

/* Change SERVER_IP to appropriate values */
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 5000
#define SERVER_LENGTH 10
#define SERVER_BUFF 20

/* Compilation notes:
   ------------------
	1. Compile the server program (gcc -o tcp_conc_server tcp_concurrent_server.c)
	2. Compile the client program (gcc -o tcp_conc_client tcp_concurrent_client.c)
	3. Run the server program (./tcp_conc_server)
	4. Open multiple terminals and run client programs separately (./tcp_conc_client)
	5. The idea is to see the server handling multiple connections concurrently
	6. Start with simple data exchange and make it exchange structure data
	7. This is how a typical client-server based protocol is developed 
*/

int main()
{

	int sock_fd, data_sock_fd,pid;
    struct sockaddr_in serv_addr; 
	char serv_buffer[SERVER_BUFF];

	printf("TCP_SERVER: Concurrent server is waiting...n");

	/* Create a TCP socket */
	/* This first socket is control connection, all clients connect here */
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);

	/* Bind it to a particular IP address & port) */
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    serv_addr.sin_port = htons(SERVER_PORT); 

    bind(sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 

	/* Wait and listen for incoming connections */
    listen(sock_fd, SERVER_LENGTH);

	/* Get into infinite loop as this is a server */
	while (1)
	{

   		/* If there are any, accept and create a new data socket */
		/* Accept returns means TCP threeway handshake (SYN-ACK-SYN) successful
       	   The new socket (second socket) is data connecion. For every client 
           now we need to fork a child in order to handle separate connections */
    	data_sock_fd = accept(sock_fd, (struct sockaddr*)NULL, NULL); 

		pid = fork();
		
		/* Let the child handle data connection */
		if (pid == 0)
		{

			printf("New child forked...awaiting for input from clientn");

    		/* Try to get some actual data from client */
			/* TODO: Instead of simple string pass a structure to get a real feel of 
			   each client passing different type of data */
			recv(data_sock_fd, (void *) serv_buffer,SERVER_BUFF,0);

			/* Print the data received from client */
			printf("Here is the client data: %sn",serv_buffer);

			/* Close the data socket now */
			close(data_sock_fd);

			/* Let the child exit, its done its job now */
			exit(0);

		}
	}
	
	/* It doesn't get here, incase it gets close the control socket */
	close(sock_fd);
}

Example output:

Linux Internals Programming Examples - 21

Brief:

Sockets offer interfaces with TCP/IP stack inside Linux. Kernel, using which remote connections can be established over a network. This program demonstrates various steps to establish successful connection using UDP sockets as a connection-less client.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t022_ch5_udp_client.c
 *   Title          : IPC mechanism - Usage of UDP socket - Client 
 *   Description    : Sockets offer interfaces with TCP/IP stack inside Linux 
 *                    Kernel, using which remote connections can be established
 *                    over a network. This program demonstrates various steps
 *                    to establish successful connection using UDP sockets as
 *                    a connection-less client. 
 *
 *----------------------------------------------------------------------------*/
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>

#define SERVER_IP_ADDRESS 	"127.0.0.1"
#define SERVER_PORT       	5000
#define CLIENT_BUFF_SIZE		20

int main()
{
	int sock_fd,c_size;
	char client_buff[CLIENT_BUFF_SIZE];
	struct sockaddr_in serv_addr; 

	/* Create a client socket */
	if((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	{
		printf("Error: Could not create socketn");
		return 1;
	} 

	/* Binding with client socket is optional here */

	/* Populate it with server address details */
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERVER_PORT); 
	serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDRESS);

	/* Get the message from client */
	printf("Enter the message you want to sent to server:n");
	fgets(client_buff, CLIENT_BUFF_SIZE, stdin);

	/* Send the message to server */
	c_size = sendto(sock_fd, (void *)&client_buff, CLIENT_BUFF_SIZE,0, 
  (struct sockaddr *)&serv_addr,sizeof(serv_addr));

	if(c_size)
		printf("Message sent to server successsfully, please checkn");
	else
		printf("Error: Message sendn");
}

Example output:

Linux Internals Programming Examples - 22
 

Brief:

Sockets offer interfaces with TCP/IP stack inside Linux. Kernel, using which remote connections can be established over a network. This program demonstrates various steps to establish successful connection using UDP sockets as a connection-less server.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Tue 01 Mar 2016 16:18:10 IST
 *   File           : li_t022_ch5_udp_server.c
 *   Title          : IPC mechanism - Usage of UDP socket - Server 
 *   Description    : Sockets offer interfaces with TCP/IP stack inside Linux 
 *                    Kernel, using which remote connections can be established
 *                    over a network. This program demonstrates various steps
 *                    to establish successful connection using UDP sockets as
 *                    a connection-less server. 
 *
 *----------------------------------------------------------------------------*/
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_IP  		"127.0.0.1"
#define SERVER_PORT 	5000
#define SERVER_LENGTH 	10
#define SERVER_BUFF		20

int main()
{

	int sock_fd,buffer_len,cli_len;
    struct sockaddr_in serv_addr; 
    struct sockaddr    cli_addr; 
	char serv_buffer[SERVER_BUFF];

	printf("Emertxe: Server is waiting...n");

	/* Create a TCP socket */
    sock_fd = socket(AF_INET, SOCK_DGRAM, 0);

	/* Bind it to a particular IP address & port) */
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    serv_addr.sin_port = htons(SERVER_PORT); 

    bind(sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 

    /* Try to get some actual data from client */
	cli_len = sizeof(struct sockaddr_in);
    recvfrom(sock_fd,(void *)serv_buffer,SERVER_BUFF,0,(struct sockaddr *) &cli_addr, &cli_len);

	/* Print the data received from client */
	printf("Here is the client data: %s",serv_buffer);

	/* Close the socket now */
	close(sock_fd);
}

Example output:

Linux Internals Programming Examples - 22

Brief:

As a part of socket APIs,select helps in multiplexing  multiple I/O for synchronous handling. Here is a simple program using select() to read from stdin with a  time-out.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:56:09 IST
 *   File           : li_t023_ch5_select_simple.c
 *   Title          : IPC mechanism - Synchronous multiplexing - Select 
 *   Description    : As a part of socket APIs,select helps in multiplexing 
 *                    multiple I/O for synchronous handling. Here is a simple
 *                    program using select() to read from stdin with a time-out
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int main() 
{
	fd_set rfds;
	struct timeval tv;
	int retval;
	char buff[11] = {0};

	/* Watch stdin (fd 0) to see when it has input. */
	FD_ZERO(&rfds);
	FD_SET(0, &rfds);
	/* Wait up to five seconds. */
	tv.tv_sec = 5;
	tv.tv_usec = 0;
	printf("Enter the string in 5 secsn");
	retval = select(1, &rfds, NULL, NULL, &tv);
	/* Don’t rely on the value of tv now! */

	if (retval == -1)
		perror("select()");
	else if (retval)
	{
		/* FD_ISSET(0, &rfds) will be true. */
		read(0, buff, 10);
		printf("Entered data is %sn", buff);
	}
	else
		printf("No data within five seconds.n");

	return 0;
}

Example output:

Linux Internals Programming Examples - 23
 

Brief:

As a part of socket APIs,select helps in multiplexing multiple I/O for synchronous handling. Here is a simple program using select() as concurrent TCP client.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t024_ch5_tcp_select_client.c
 *   Title          : IPC mechanism - Concurrent TCP server - Select 
 *   Description    : As a part of socket APIs,select helps in multiplexing 
 *                    multiple I/O for synchronous handling. Here is a simple
 *                    program using select() as concurrent TCP client.
 *
 *----------------------------------------------------------------------------*/

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>

#define SERVER_IP_ADDRESS 	"127.0.0.1"
#define SERVER_PORT       	5000
#define CLIENT_BUFF_SIZE	20

int main()
{
	int sock_fd,c_size;
	char client_buff[CLIENT_BUFF_SIZE];
	struct sockaddr_in serv_addr; 

	/* Create a client socket */
	if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		printf("Error: Could not create socketn");
		return 1;
	} 

	/* Binding with client socket is optional here */

	/* Populate it with server address details */
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERVER_PORT); 
	serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDRESS);

	/* Get the message from client */
	printf("Enter the message you want to sent to server:n");
	fgets(client_buff, CLIENT_BUFF_SIZE, stdin);

	if(connect(sock_fd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) != 0)
		printf("Error connecting to servern");
	else
		printf("Connection successfuln");

	/* Send the message to server */
	c_size = send(sock_fd, (void *)&client_buff, CLIENT_BUFF_SIZE,0);

	if(c_size)
		printf("Message sent to server successsfully, please checkn");
	else
		printf("Error: Message sendn");

	close(sock_fd);
}

Example output:

Linux Internals Programming Examples - 24

Brief:

As a part of socket APIs,select helps in multiplexing multiple I/O for synchronous handling. Here is a simple program using select() as concurrent TCP server.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t024_ch5_tcp_select_server.c
 *   Title          : IPC mechanism - Concurrent TCP server - Select 
 *   Description    : As a part of socket APIs,select helps in multiplexing 
 *                    multiple I/O for synchronous handling. Here is a simple
 *                    program using select() as concurrent TCP server.
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define PORT    5000
#define MAXMSG  512

int read_from_client (int filedes)
{
	char buffer[MAXMSG];
	int nbytes;

	nbytes = read (filedes, buffer, MAXMSG);
	if (nbytes < 0)
	{
		/* Read error. */
		perror("read");
		exit(EXIT_FAILURE);
	}
	else if (nbytes == 0)
		/* End-of-file. */
		return -1;
	else
	{
		/* Data read. */
		printf("Server: got message: `%s'n", buffer);
		return 0;
	}
}

int make_socket(short port)
{
	int sock;
	struct sockaddr_in name;

	/* Create the socket. */
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock < 0)
	{
		perror("socket");
		exit(EXIT_FAILURE);
	}

	/* Give the socket a name. */
	name.sin_family = AF_INET;
	name.sin_port = htons(port);
	name.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(sock, (struct sockaddr *) &name, sizeof (name)) < 0)
	{
		perror ("bind");
		exit (EXIT_FAILURE);
	}

	return sock;
}
int main()
{
	int sock;
	fd_set active_fd_set, read_fd_set;
	int i;
	struct sockaddr_in clientname;
	socklen_t size;

	/* Create the socket and set it up to accept connections. */
	sock = make_socket(PORT);
	if (listen (sock, 1) < 0)
	{
		perror ("listen");
		exit (EXIT_FAILURE);
	}

	/* Initialize the set of active sockets. */
	FD_ZERO (&active_fd_set);
	FD_SET (sock, &active_fd_set);

	while (1)
	{
		read_fd_set = active_fd_set;
		/* Block until input arrives on one or more active sockets. */
		if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0)
		{
			perror ("select");
			exit (EXIT_FAILURE);
		}

		/* Service all the sockets with input pending. */
		for (i = 0; i < FD_SETSIZE; ++i)
			if (FD_ISSET (i, &read_fd_set))
			{
				/* Connection request on original socket. */
				if (i == sock)
				{
					int new;
					size = sizeof (clientname);
					new = accept (sock, (struct sockaddr *)&clientname, &size);
					if (new < 0)
					{
						perror ("accept");
						exit (EXIT_FAILURE);
					}
					printf("Server: connect from host %s, port %d.n", 
                      					inet_ntoa (clientname.sin_addr),
                      					ntohs (clientname.sin_port)); 
					FD_SET (new, &active_fd_set);
				}
				else
				{
					/* Data arriving on an already-connected socket. */
					if (read_from_client (i) < 0)
					{
						close (i);
						FD_CLR (i, &active_fd_set);
					}
				}
			}
	}
}

 

Example output:

Linux Internals Programming Examples - 24

 

Chapter 6 : Multi Threading in Linux

Brief:

Threads offer efficient way to achieve multi-tasking compared to processes. In this example POSIX thread library calls are used to create a new thread.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t025_ch6_thread_creation.c
 *   Title          : POSIX threads (pThread) - Creating new thread 
 *   Description    : Threads offer efficient way to achieve multi-tasking 
 *                    compared to processes. In this example POSIX thread 
 *                    library calls are used to create a new thread. 
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>


void *thread_entry_function(void * arg)
{
	printf("Inside thread functionn");
	return NULL;
}

int main()
{
	pthread_t threadID;

	pthread_create(&threadID, NULL, thread_entry_function,NULL);
	pthread_join(threadID, NULL);

	/* TODO:
	 * 1. Pass a thread into a thread via argument 4
	 * 2. Return a value from thread via pthread_join
	 * 3. Implement a meaningful logic by calculating factorial
	 */

	printf("Back in main thread, thread value %dn", threadvalue);
}

Example output:

Linux Internals Programming Examples - 25

Brief:

Threads offer efficient way to achieve multi-tasking compared to processes. In this example POSIX thread library calls are used to create a new thread and various mechanisms to return values from thread for a sample functionality of factorial.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t026_ch6_thread_data.c
 *   Title          : POSIX threads (pThread) - Returning value from thread 
 *   Description    : Threads offer efficient way to achieve multi-tasking 
 *                    compared to processes. In this example POSIX thread 
 *                    library calls are used to create a new thread and various
 *                    mechanisms to return values from thread for a sample 
 *                    functionality of factorial. 
 *
 *----------------------------------------------------------------------------*/
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>

typedef struct fact_calc
{
	int num;
	int result;
}factcalc;

int fact_calculate(int num)
{
	int fact=1;
	int i;

	for(i=1;i<=num;i++)
		fact = fact*i;

	printf("The factorial value is:%dn",fact);

	return fact;
}

void* fact_method1 (void *input)
{
	int num = *(int*) input;
	int *result;


	/* Do a dynamic memory allocation, better way */
	result = (int*)malloc(4);
	*result = fact_calculate(num);
	return(result);
}

void* fact_method2 (void *input)
{
	int num = *(int*) input;
	int result;

	result = fact_calculate(num);

	/* This is a Hack way, sending value as a pointer */
	return((void *)(long)result);
}

void* fact_method3 (void *input)
{
	factcalc *ptr = (factcalc *)input;

	/* Still a better way, use the variable allocated in main */
	ptr->result = fact_calculate(ptr->num);
	return NULL;
}

int main()
{
	int value = 6;
	int *result;
	int output;
	pthread_t thread_1,thread_2,thread_3;
	factcalc input;

	/* Method - 1 -- Dynamic memory allocation */
	pthread_create(&thread_1,NULL,fact_method1,(void*)&value);
	pthread_join(thread_1,(void **)&result);
	printf("The result-1 is: %dn",*result);

	/* Method - 2 -- Hack way */
	pthread_create(&thread_2,NULL,fact_method2,(void*)&value);
	pthread_join(thread_1,(void **)&output);
	printf("The result-2 is: %dn",output);

	/* Method -3 -- Allocate locally */
	input.num = 6;
	pthread_create(&thread_3,NULL,fact_method3,(void*)&input);
	pthread_join(thread_1,NULL);
	printf("The result-3 is: %dn",input.result);

}

Example output: 

Linux Internals Programming Examples - 26

Brief:

Threads offer multiple options to set attributes, using which multi-tasking can be achieved more effectively. One of them being joint & disjoint threads, demonstrated here.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t027_ch6_thread_attributes.c
 *   Title          : POSIX threads (pThread) - Joint & Disjoint threads
 *   Description    : Threads offer multiple options to set attributes, using 
 *                    which multi-tasking can be achieved more effectively. One 
 *                    of them being joint & disjoint threads,demonstrated here. 
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <pthread.h>


void *thread_entry_function(void * arg)
{
	int loop;

	thread_number = (int *)arg;

	/* 
	 * TODO: Calculate factorial here 
	 */

	return NULL;
}

int main()
{

	pthread_t threadID;
	pthread_attr_t attr;

	/* Initialize the attribute */
	pthread_attr_init (&attr);

	/* Set the attribute for a detached thread */
	pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);

	/* Now create a thread with this attribute */ 
	pthread_create(&threadID, &attr, thread_entry_function, &threadvalue);

	/* No need to call pthread_join here, as we are not going to wait */

	/* TODO:
	 *      1. Why should we put the sleep below? Remove and check
	 *      2. Create another thread with default (ATTACHED) state and compare
	 */
	sleep(2);
	printf("Back in main threadn");
	pthread_attr_destroy (&attr);
}

Example output:

Linux Internals Programming Examples - 27

 

Brief:

Threads offer multiple options to set attributes, using which multi-tasking can be achieved more effectively. One of them being thread cancellation,demonstrated here.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t028_ch6_thread_cancel.c
 *   Title          : POSIX threads (pThread) - Thread cancellation 
 *   Description    : Threads offer multiple options to set attributes, using 
 *                    which multi-tasking can be achieved more effectively. One 
 *                    of them being thread cancellation,demonstrated here. 
 *
 *----------------------------------------------------------------------------*/
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>

void *thread_function(void *arg);

int main()
{
	int res;
	pthread_t a_thread;
	void *thread_result;

	res = pthread_create(&a_thread, NULL, &thread_function, NULL);
	if(res != 0)
	{
		perror("Thread creation failed");
		exit(EXIT_FAILURE);
	}

	sleep(3);
	printf("Cancelling thread...n");
	res = pthread_cancel(a_thread);
	if(res != 0)
	{
		perror("Thread Cancellation failed");
		exit(EXIT_FAILURE);
	}
	exit(EXIT_SUCCESS);
}

void *thread_function(void *arg)
{
	int i, res; 
	res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	if(res != 0)
	{
		perror("Thread pthread_setcancelstate failed");
		exit(EXIT_FAILURE);
	}
	printf("Thread_fuction is still runningn");
	for(i = 0; i < 10; i++)
	{
		printf("nThread function is running (%d)...n", i);
		sleep(1);
	}
	pthread_exit(0);
}

Example output:

Linux Internals Programming Examples - 28

Brief:

Threads are prone to race conditions due to shared data problem. Here is an example of global variable being the reason for race condition.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t029_ch7_thread_race.c
 *   Title          : POSIX threads (pThread) - Race conditions 
 *   Description    : Threads are prone to race conditions due to shared data 
 *                    problem. Here is an example of global variable being the
 *                    reason for race condition. 
 *
 *----------------------------------------------------------------------------*/
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

pthread_t thread_1;
pthread_t thread_2;
int counter;

void* thread_function(void *arg)
{
    counter += 1;
    printf("nJob %d startedn", counter);
	sleep(2);
    printf("nJob %d finishedn", counter);
    return NULL;
}

int main(void)
{

   pthread_create(&thread_1,NULL,thread_function,NULL);
   pthread_create(&thread_2,NULL,thread_function,NULL);

   pthread_join(thread_1,NULL);
   pthread_join(thread_2,NULL);

   return 0;
}

Example output:

Linux Internals Programming Examples - 29

Brief:

Threads are prone to race conditions due to shared data problem. One of the way race conditions can be avoided by using mutex by protecting shared data, as shown below.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t030_ch7_thread_race_mutex_solution.c
 *   Title          : POSIX threads (pThread) - Mutex usage for race conditions 
 *   Description    : Threads are prone to race conditions due to shared data 
 *                    problem. One of the way race conditions can be avoided 
 *                    by using mutex by protecting shared data, as shown below.
 *
 *----------------------------------------------------------------------------*/
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

pthread_t thread_1;
pthread_t thread_2;
int counter;
pthread_mutex_t lock;

void* thread_function(void *arg)
{
    pthread_mutex_lock(&lock);
    counter += 1;
    printf("nJob %d startedn", counter);
	sleep (2);
    printf("nJob %d finishedn", counter);
    pthread_mutex_unlock(&lock);
    return NULL;
}

int main(void)
{

    if (pthread_mutex_init(&lock, NULL) != 0)
    {
        printf("nPthread: mutex init failedn");
        return 1;
    }

   pthread_create(&thread_1,NULL,thread_function,NULL);
   pthread_create(&thread_2,NULL,thread_function,NULL);

   pthread_join(thread_1,NULL);
   pthread_join(thread_2,NULL);
   pthread_mutex_destroy(&lock);
   return 0;
}

Example output:

Linux Internals Programming Examples - 30
 

Brief:

Threads are prone to race conditions due to shared data problem. One of the way race conditions can be avoided by using semaphores by protecting shared data, as shown below.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t031_ch7_thread_semaphores.c
 *   Title          : POSIX threads (pThread) - Semaphore usage
 *   Description    : Threads are prone to race conditions due to shared data 
 *                    problem. One of the way race conditions can be avoided 
 *                    by using semaphores by protecting shared data, as shown
 *                    below.
 *
 *----------------------------------------------------------------------------*/
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>

sem_t count;

void* fun (void * parm)
{
	int k = 5;
	int value;

	sem_wait(&count);
	/* Entering critical section */
	sem_getvalue(&count,&value);
	printf("The semaphore count before loop: %dn",value);
	while(k)
	{
		printf("Inside loop, Value of K=%dn",k);
		k--;
		sleep(1);
	}
	sem_post(&count);
	/* Exiting critical section */
	sem_getvalue(&count,&value);
	printf("The semaphore count after loop: %dn",value);
		 
}

int main()
{
	int i;
	pthread_t tid[5];

	sem_init(&count, 0, 3);

	for(i=0; i<3; i++)
		pthread_create (&tid[i], NULL, &fun, NULL);

	for(i=0; i<3; i++)
		pthread_join(tid[i], NULL);

	/*
	 * TODO:  1. Change the value of loop index (i) to 5 and see change in print pattern
	 *        2. Change the semaphore initial value to 5 and see change in print pattern
	 *        3. Change the semaphore initial value to 2 and see change in print pattern
	 *        4. Change the semaphore initial value to 1 
   *				   (Binary Mutex) and see change in print pattern
	 */

	return 0;
}

Example output:

Linux Internals Programming Examples - 31

Brief:

Producer consumer problem demonstration using threads.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t032_ch7_thread_prod_cons.c
 *   Title          : POSIX threads (pThread) - Producer consumer problem 
 *   Description    : Producer consumer problem demonstration using threads.
 *
 *----------------------------------------------------------------------------*/
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include <unistd.h> 

#define MAX_BUFF   100

void *consume(void *arg);
void *produce(void *arg);
int buf[MAX_BUFF], front, rear;
/* Here lock is used to create a critical section
 *  full and empty used to signaling events to other threads
 */
sem_t lock, full, empty;

int main()
{
	pthread_t tid1,tid2;
	/* lock is a binary semaphore used to make a critical same as mutex 
	 * To make sure only one thread accessing at a time*/
	sem_init(&lock, 0, 1);
	/* full is used to check queue is empty or not */
	sem_init(&full, 0, 1);
	/* empty is used to check queue is full or not */
	sem_init(&empty, 0, MAX_BUFF);
	pthread_create(&tid1, NULL, produce, NULL);
	pthread_create(&tid2, NULL, consume, NULL);
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
}
void *produce(void *arg)
{
	int i;
	for(i=0;i<10;i++)
	{
		/* Now this is same as is_queue_full() 
		 * before storing value in queue */
		sem_wait(&empty);
		sem_wait(&lock);
		printf("produced item is %dn", i);
		buf[(++rear)%MAX_BUFF] = i;
		sleep(1);
		sem_post(&lock);
		/* This is to inform consumer that data is available in queue */
		sem_post(&full);
	}
	return NULL;
}
void *consume(void *arg)
{
	int item, i;
	for(i = 0; i < 10; i++)
	{
		/* wait untill data is available in queue same as
		 * is_queue_empty() */
		sem_wait(&full);
		sem_wait(&lock);
		item=buf[(++front) % MAX_BUFF];
		printf("consumed item is %dn", item);
		sleep(1);
		sem_post(&lock);
		/* Notifynig consumer that data consumed and psition is available */
		sem_post(&empty);
	}
	return NULL;
}

Example output:

Linux Internals Programming Examples - 32
 

Brief:

Race condition is common in multi-processing situation as shared data condition will come there as well.Problem is solved by process semaphores, demonstrated here.

 

Source Code:

/*------------------------------------------------------------------------------ 
 *
 *   Author         : Emertxe (https://www.emertxe.com) 
 *   Date           : Thu 12 May 2016 15:59:19 IST
 *   File           : li_t033_ch7_semaphore_process.c
 *   Title          : Semaphore usage - Multi-process condition  
 *   Description    : Race condition is common in multi-processing situation
 *                    as shared data condition will come there as well.Problem 
 *                    is solved by process semaphores, demonstrated here. 
 *
 *----------------------------------------------------------------------------*/
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<unistd.h>

int main()
{
	int semid, pid;
	struct sembuf sop;
	semid = semget(0x20, 1, IPC_CREAT | 0666);
	semctl(semid, 0, SETVAL, 1);
	pid = fork();
	if(pid == 0)
	{
		printf("child before semopn");
		sop. sem_num = 0; 
		sop.sem_op = -1;
		sop.sem_flg = 0;
		semop(semid, &sop, 1);
		printf("Child in critical sectionn");
		sleep(10);
		printf("Child coming out of critical sectionn");
		sop.sem_num = 0; 
		sop.sem_op = 1; 
		sop.sem_flg = 0;
		semop(semid, &sop, 1);
	}
	else
	{
		printf("parent before semopn");
		sop. sem_num = 0; 
		sop.sem_op = -1;
		sop.sem_flg = 0;
		semop(semid, &sop, 1);
		printf("Parent in critical sectionn");
		sleep(10);
		printf("Parent coming out of critical sectionn");
		sop.sem_num = 0; 
		sop.sem_op = 1; 
		sop.sem_flg = 0;
		semop(semid, &sop, 1);
	}
	return 0;
}

Example output:

Linux Internals Programming Examples - 33