C program to use clone system call

Introduction to "Clone" system call

 clone() creates a new process, in a manner similar to fork(2).

     Unlike fork(2), clone() allows the child process to share parts of its execution context with the calling process, such as the memory space, the table of file descriptors, and  the
 table of signal handlers. 

     The main use of clone() is to implement threads: multiple threads of control in a program that run concurrently in a shared memory space.

     When  the child process is created with clone(), it executes the function fn(arg).  (This differs from fork, where execution continues in the child from the point of the fork call.)  The fn argument is a pointer to a function that is called by the child process at the beginning of its execution.  The arg argument is passed to the fn function.

      When the fn(arg) function application returns, the child process terminates.  The integer returned by fn is the exit code for the child process.  The child process may also  termi‐
nate explicitly by calling exit(2) or after receiving a fatal signal.

       The  child_stack  argument  specifies  the  location of the stack used by the child process.  Since the child and calling process may share memory, it is not possible for the child process to execute in the same stack as the calling process.  The calling process must therefore set up memory space for the child stack  and  pass  a  pointer  to  this  space  to clone().   Stacks  grow downward on all processors that run Linux (except the HP PA processors), so child_stack usually points to the topmost address of the memory space set up for the child stack.

C program


#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

void *pchild_stack =  NULL;

int fn(void *arg)
{
    strcpy((char *)pchild_stack, "aricent");
    printf("I am the child my pid :%d parent's parent pid : %d pchild_stack: %s \n"
            ,getpid() , getppid(), (char *)pchild_stack);

    return 0;
}

void main(int argc, char *argv[])
{
    pchild_stack = malloc(1024 * 1024);
    if ( pchild_stack == NULL ) {
        printf("ERROR: Unable to allocate memory.\n");
        exit(EXIT_FAILURE);
    }

    strcpy((char *)pchild_stack, "google");
    printf("I am the parent my pid :%d parent's parent pid : %d pchild_stack: %s\n",
            getpid() , getppid(), (char *)pchild_stack);

    int pid = clone(fn, (char *)pchild_stack + (1024 * 1024), SIGCHLD, argv[1]);
    if ( pid < 0 ) {
        printf("ERROR: Unable to create the child process.\n");
        exit(EXIT_FAILURE);
    }

    printf("INFO: Child process terminated.\n");
    wait(NULL);


    printf("I am the parent my pid :%d parent's parent pid : %d pchild_stack: %s\n",
            getpid() , getppid(), (char *)pchild_stack);
    free(pchild_stack);
    pchild_stack = NULL;

}


Output

Neelkanth_98$ ./a.out
I am the parent my pid :29371 parent's parent pid : 28022 pchild_stack: google
INFO: Child process terminated.
I am the child my pid :29372 parent's parent pid : 29371 pchild_stack: aricent
I am the parent my pid :29371 parent's parent pid : 28022 pchild_stack: google


C Program on how to use "umask" system call

Neelkanth_39$ cat umask.c

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main () {
    FILE *fp;

    errno = 0;

   /*
    * RETURN VALUE
    * This system call always succeeds and the previous value of the mask is returned.
    */
    int old_mask = umask(0);
    printf("old mask : %d\n", old_mask);

    system("rm -rf neelu");

    /* make directory  */
    int dir_result = mkdir("neelu", 0777);
    if(dir_result != 0 && errno != EEXIST){
        printf( "Value of errno: %s\n", strerror(errno));
    }
    else if (errno == EEXIST)
    {
        printf("error code: %s", strerror(errno));
    }

    int old_mask1 = umask(old_mask);
    printf("old mask : %d\n", old_mask1);

    return(0);
}


Output

Neelkanth_39$ ./a.out
old mask : 2
old mask : 0


C program to define macro PRINTF for printf , where in PRINTF takes same arguments as printf and also prints timestamp

neelkanth_surekha# cat printf.c

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

#define LOG_INIT()              time_t ltime; /* calendar time */ \
                                char *ptr;\

#define PRINTF(...)     ltime = time(NULL); /* get current cal time */ \
                                ptr = asctime( localtime(&ltime));\
                                ptr[strlen(ptr)-1] = '\0';\
                                printf("%s: ", ptr); \
                                printf(__VA_ARGS__); printf("\n");


void print_logs()
{
   LOG_INIT();
   PRINTF("%s", "neelu");
   sleep(2);
   PRINTF("%s", "peelu");
   sleep(2);
   PRINTF("%s", "meelu");
}


void main()
{
    print_logs();

}

Output:

neelkanth_surekha#./a.out 
Thu Nov 23 00:29:32 2017: neelu
Thu Nov 23 00:29:34 2017: peelu
Thu Nov 23 00:29:36 2017: meelu

C Program to implement Multi-threaded program

C Program to implement Multi-threaded program

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define NUM_THREADS 2

/* create thread argument struct for thr_func() */
typedef struct _thread_data_t {
    int tid;
    double stuff;
} thread_data_t;

/* thread function */
void *thr_func(void *arg) {
    thread_data_t *data = (thread_data_t *)arg;

    fprintf(stdout, "hello from thr_func, thread id: %d\n", data->tid);

    pthread_exit(NULL);
}

int main(int argc, char **argv) {
    pthread_t thr[NUM_THREADS];
    int i, rc;
    /* create a thread_data_t argument array */
    thread_data_t thr_data[NUM_THREADS];

  
  /* create threads */
    for (i = 0; i < NUM_THREADS; ++i) {
        thr_data[i].tid = i;
        if ((rc = pthread_create(&thr[i], NULL, thr_func, &thr_data[i]))) {
            fprintf(stderr, "error: pthread_create, rc: %d\n", rc);
            return EXIT_FAILURE;
        }
    }
    /* block until all threads complete */
    for (i = 0; i < NUM_THREADS; ++i) {
        pthread_join(thr[i], NULL);
    }

    return EXIT_SUCCESS;
}

 

output:

gcc thread.c -lpthread

neelkanth_surekha#ps -elfT | grep a.out
0 S neelkan+  3273  3273  2526  0  80   0 - 22112 futex_ 01:37 pts/19   00:00:00 ./a.out
1 R neelkan+  3273  3274  2526 99  80   0 - 22112 -      01:37 pts/19   00:00:06 ./a.out
1 R neelkan+  3273  3275  2526 99  80   0 - 22112 -      01:37 pts/19   00:00:06 ./a.out
0 S neelkan+  3277  3277  2526  0  80   0 -  3556 pipe_w 01:37 pts/19   00:00:00 grep --color=auto a.out


C program to print error code, if directory is already present [system call: mkdir]

C program to print error code, if directory is already present [system call: mkdir]


#include <stdio.h>
#include <string.h>
#include <errno.h>

int main () {
    FILE *fp;

    errno = 0;
    int dir_result = mkdir("neelu", 0755);
    if(dir_result != 0 && errno != EEXIST){
        printf( "Value of errno: %s\n", strerror(errno));
    }
    else if (errno == EEXIST)
    {
        printf("error code: %s", strerror(errno));
    }

    return(0);
}

C Program to create a Zombie child when the parent exits without "wait" system call.

/* C program to demonstrate Zombie Process.Child becomes Zombie as parent is sleepingwhen child process exits.*/


#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
    // Fork returns process id
    // in parent process
    pid_t child_pid = fork();

    // Parent process
    if (child_pid > 0) {
        sleep(100);

    }

    // Child process
    else {
        sleep(50);
        exit(0);
    }
    return 0;
}


Output:

Neelkanth_98$ ps -elf  | grep a.out
0 S labuser  28903 28022  0  80   0 -  1052 hrtime 21:12 pts/1    00:00:00 ./a.out
1 Z labuser  28904 28903  0  80   0 -     0 exit   21:12 pts/1    00:00:00 [a.out] <defunct>
0 S labuser  29099 29073  0  80   0 -  3990 pipe_w 21:13 pts/7    00:00:00 grep --color=auto a.out

C program on "waipid" system call usage [WIFSTOPPED and WIFCONTINUED]

C program on "waipid" system call usage [WIFSTOPPED and WIFCONTINUED]



"From the code in the above weblink, minor changes are made to demonstrate WIFSTOPPED and WIFCONTINUED. 

Also, refer the below link on how to test this code:

Note:
When you use SIGSTOP to a process it will pause the process. It will not resume automatically unless you send a SIGCONT signal to it. This is great because it allows you to pause a process without terminating it.

Neelkanth_39$ cat child_main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{

    /* the program should take 2 arguments */
    if (((argc >1) && (argc <= 3)))
    {
        printf("child: process name: %s\n", argv[0]);
        printf("child: arguments %s %s\n", argv[1], argv[2]);
    } else {
        printf("child: enter only 2 random strings\n");
        exit(1);
    }

    /* The child process would run indefinitely now */
    printf("child: Child process goes into infinite while loop\n");
    printf("child: Issue (Kill -19 and  Kill -18 in sequence) "
            "to child process and see what happens\n");

    while(1) {
       sleep(10);
    }

    return 0;
}


Neelkanth_39$ cat parent_main_3.c
#include <errno.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>

int main()
{
    pid_t child_pid;
    int status;
    /* now create new process */
    child_pid = fork();
    int ret;

    if (child_pid >= 0) /* fork succeeded */
    {
        if (child_pid == 0) /* fork() returns 0 for the child process */
        {
            printf("parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
            printf("parent: start child process!\n");
            printf("parent: child PID =  %d, parent pid = %d\n", getpid(), getppid());

            char *cmd[] = {"./child1", "neel", "rockstar", NULL};
            return execvp(cmd[0], cmd); // call child1 process

        }
        else /* parent process */
        {
            printf("parent: *****************************************************\n");
            printf("parent: parent process!\n");
            printf("parent: parent PID =  %d, child pid = %d\n", getpid(), child_pid);

            /* wait for child to exit, and store child's exit status */
            printf("parent: WAIT FOR THE CHILD PROCESS TO TERMINATE\n");
            printf("parent: *****************************************************\n");

            /*
               WUNTRACED   also return if a child has stopped (but not traced via
                           ptrace(2)).  Status for traced children which have
                           stopped is provided even if this option is not specified.

               WCONTINUED (since Linux 2.6.10)
                           also return if a stopped child has been resumed by deliv‐
                           ery of SIGCONT.
             */

            do {
                ret = waitpid(child_pid, &status, WUNTRACED | WCONTINUED);
                if (ret == -1) {
                    perror("waitpid");
                    exit(1);
                }

                /*
                   WIFSTOPPED(wstatus)
                   returns true if the child process was stopped by delivery of a
                   signal; this is possible only if the call was done using WUN‐
                   TRACED or when the child is being traced (see ptrace(2)).
                   kill -19 [SIGSTOP]
                 */
                if (WIFSTOPPED(status)) {
                    printf("parent: stat value: %d Exit status: %d\n", status, WSTOPSIG(status));
                    psignal(WSTOPSIG(status), "parent: child received STOP signal: "
                            "Exit signal");
                    printf("parent: Child process to PAUSE at this point \n");
                    printf("parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
                }

                /*
                   WIFCONTINUED(wstatus)
                   (since Linux 2.6.10) returns true if the child process was
                   resumed by delivery of SIGCONT.
                   kill -18 [SIGCONT]
                 */
                if (WIFCONTINUED(status)) {
                    printf("parent: stat value: %d Exit status: %d\n", status, WIFCONTINUED(status));
                    printf("parent: child received SIGCONT signal\n");
                    printf("parent: Child process to RESUME from the point where it was stopped earlier\n");
                    printf("parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
                }



                /*If child has exited on return from it's main function or exit(0): */
                if (WIFEXITED(status)) {
                    printf("parent: Child process has exited. exit code: %d\n", WEXITSTATUS(status));
                    printf("parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
                }
                /* if child has exited on receiving an exception signal
                 * e.g. kill -11 (SIGSEGV),
                 -3  (SIQUIT),
                 -4  (SIGILL),
                 -5  (SIGTRAP),
                 -6  (SIGABRT),
                 -7  (SIGBUS),
                 -8  (SIGFPE),
                 */
                if (WIFSIGNALED(status) && WCOREDUMP(status)) {
                    printf("parent: stat value: %d Exit status: %d\n", status, WTERMSIG(status));
                    psignal(WTERMSIG(status), "parent: child received exception signal: "
                            "Exit signal");
                    printf("parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
                }
                /* if child has exited on receiving a termination signal
                 * e.g. kill -15 (SIGTERM),
                 -2  (SIGINT),
                 -9  (SIGKILL),
                 -1  (SIGHUP),
                 -13 (SIGPIPE),
                 -14 (SIGALRM),
                 -16 (SIGSTKFLT),
                 */
                else if (WIFSIGNALED(status)) {
                    printf("parent: stat value: %d Exit status: %d\n", status, WTERMSIG(status));
                    psignal(WTERMSIG(status), "parent: Child received Termination signal: "
                            "Exit signal");
                    printf("parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
                }
            }
            /* Come out of while loop, only when child process exits 'or'
             * terminates on receiving an exception signal.
             * If child process receives SIGSTOP (kill -19), parent can still wait
             * till the child actually terminates.
             */
            while((!WIFEXITED(status)) && (!WIFSIGNALED(status)));

            printf("parent: *****************************************************\n");
            printf("parent: Parent exits now!\n\n");
            printf("parent: *****************************************************\n");
            exit(0);  /* parent exits */
        }
    }
    else /* failure */
    {
        perror("fork");
        exit(0);
    }
}

Output:

Terminal 1:
Neelkanth_39$ ./parent_main_3
parent: *****************************************************
parent: parent process!
parent: parent PID =  32279, child pid = 32280
parent: WAIT FOR THE CHILD PROCESS TO TERMINATE
parent: *****************************************************
parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: start child process!
parent: child PID =  32280, parent pid = 32279
child: process name: ./child1
child: arguments neel rockstar
child: Child process goes into infinite while loop
child: Issue (Kill -19 and  Kill -18 in sequence) to child process and see what happens

parent: stat value: 4991 Exit status: 19
parent: child received STOP signal: Exit signal: Stopped (signal)
parent: Child process to PAUSE at this point
parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: stat value: 65535 Exit status: 1
parent: child received SIGCONT signal
parent: Child process to RESUME from the point where it was stopped earlier
parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: stat value: 4991 Exit status: 19
parent: child received STOP signal: Exit signal: Stopped (signal)
parent: Child process to PAUSE at this point
parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: stat value: 65535 Exit status: 1
parent: child received SIGCONT signal
parent: Child process to RESUME from the point where it was stopped earlier
parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: stat value: 4991 Exit status: 19
parent: child received STOP signal: Exit signal: Stopped (signal)
parent: Child process to PAUSE at this point
parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: stat value: 65535 Exit status: 1
parent: child received SIGCONT signal
parent: Child process to RESUME from the point where it was stopped earlier
parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@



Terminal 2:
Neelkanth_39$ kill -19 32270
Neelkanth_39$ pidof child1
32280
Neelkanth_39$ kill -19 32280
Neelkanth_39$ kill -18 32280
Neelkanth_39$ kill -19 32280
Neelkanth_39$ kill -18 32280
Neelkanth_39$ kill -19 32280
Neelkanth_39$ kill -18 32280



C program on "waipid" system call usage [WIFSTOPPED, WIFEXITED, WIFSIGNALED,WCOREDUMP]

C program on "waipid" system call usage [WIFSTOPPED, WIFEXITED, WIFSIGNALED,WCOREDUMP]



"From the code in the above weblink, "wait" system call is replaced with "waitpid". Changes are made accordingly in the code."

Neelkanth_39$ cat parent_main_2.c
#include <errno.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>

int main()
{
    pid_t child_pid;
    int status;
    /* now create new process */
    child_pid = fork();
    int ret;

    if (child_pid >= 0) /* fork succeeded */
    {
        if (child_pid == 0) /* fork() returns 0 for the child process */
        {
            printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
            printf("start child process!\n");
            printf("child PID =  %d, parent pid = %d\n", getpid(), getppid());

            char *cmd[] = {"./child1", "neel", "rockstar", NULL};
            return execvp(cmd[0], cmd); // call child1 process

        }
        else /* parent process */
        {
            printf("*****************************************************\n");
            printf("parent process!\n");
            printf("parent PID =  %d, child pid = %d\n", getpid(), child_pid);

            /* wait for child to exit, and store child's exit status */
            printf("WAIT FOR THE CHILD PROCESS TO TERMINATE\n");
            printf("*****************************************************\n");

            ret = waitpid(child_pid, &status, WUNTRACED);
            if (ret == -1) {
                perror("waitpid");
                exit(1);
            }

            /*
               WIFSTOPPED(wstatus)
               returns true if the child process was stopped by delivery of a
               signal; this is possible only if the call was done using WUN‐
               TRACED or when the child is being traced (see ptrace(2)).
               kill -19 [SIGSTOP]
             */
            if (WIFSTOPPED(status)) {
                printf("stat value: %d Exit status: %d\n", status, WSTOPSIG(status));
                psignal(WSTOPSIG(status), "child received STOP signal: "
                        "Exit signal");
                printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");          
            }

            /*If child has exited on return from it's main function or exit(0): */
            if (WIFEXITED(status)) {
                printf("Child process has exited. exit code: %d\n", WEXITSTATUS(status));
                printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
            }
            /* if child has exited on receiving an exception signal
             * e.g. kill -11 (SIGSEGV),
             -3  (SIQUIT),
             -4  (SIGILL),
             -5  (SIGTRAP),
             -6  (SIGABRT),
             -7  (SIGBUS),
             -8  (SIGFPE),
             */
            if (WIFSIGNALED(status) && WCOREDUMP(status)) {
                printf("stat value: %d Exit status: %d\n", status, WTERMSIG(status));
                psignal(WTERMSIG(status), "child received exception signal: "
                        "Exit signal");
                printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
            }
            /* if child has exited on receiving a termination signal
             * e.g. kill -15 (SIGTERM),
             -2  (SIGINT),
             -9  (SIGKILL),
             -1  (SIGHUP),
             -13 (SIGPIPE),
             -14 (SIGALRM),
             -16 (SIGSTKFLT),
             */
            else if (WIFSIGNALED(status)) {
                printf("stat value: %d Exit status: %d\n", status, WTERMSIG(status));
                psignal(WTERMSIG(status), "Child received Termination signal: "
                        "Exit signal");
                printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
            }

            printf("*****************************************************\n");
            printf("Parent exits now!\n\n");
            printf("*****************************************************\n");
            exit(0);  /* parent exits */
        }
    }
    else /* failure */
    {
        perror("fork");
        exit(0);
    }
}


Output:

*****************************************************
parent process!
parent PID =  31974, child pid = 31975
WAIT FOR THE CHILD PROCESS TO TERMINATE
*****************************************************
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
start child process!
child PID =  31975, parent pid = 31974
process name: ./child1
arguments neel rockstar
Child process goes into infinite while loop
Issue (Kill -15/ Kill -11) to child process and see what happens
stat value: 4991 Exit status: 19
child received STOP signal: Exit signal: Stopped (signal)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*****************************************************
Parent exits now!

*****************************************************
Neelkanth_39$ ./parent_main_2
*****************************************************
parent process!
parent PID =  31978, child pid = 31979
WAIT FOR THE CHILD PROCESS TO TERMINATE
*****************************************************
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
start child process!
child PID =  31979, parent pid = 31978
process name: ./child1
arguments neel rockstar
Child process goes into infinite while loop
Issue (Kill -15/ Kill -11) to child process and see what happens
stat value: 139 Exit status: 11
child received exception signal: Exit signal: Segmentation fault
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*****************************************************
Parent exits now!

*****************************************************
Neelkanth_39$ ./parent_main_2
*****************************************************
parent process!
parent PID =  31982, child pid = 31983
WAIT FOR THE CHILD PROCESS TO TERMINATE
*****************************************************
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
start child process!
child PID =  31983, parent pid = 31982
process name: ./child1
arguments neel rockstar
Child process goes into infinite while loop
Issue (Kill -15/ Kill -11) to child process and see what happens
stat value: 15 Exit status: 15
Child received Termination signal: Exit signal: Terminated
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*****************************************************
Parent exits now!

*****************************************************