Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

COMP-2560: System Programming (Fall 2022)

Lab07

Week 07

Bootstrap a Program File

The main objective of this lab will be to learn how a program file is bootstrapped into memory and become a process. We have already explained that shell does this task for us by doing system calls. Shell is an application- level (user-level) program. If the shell can bootstrap a program, why not other application-level programs.

Step 1. Library Routine to Bootstrap Program: system

Let’s write a simple program that accepts two numbers from the input and outputs the sum in the output. From the  previous  lab  (Lab06),  by  input  and  output,  we  mean  the  standard  input  (fd=STDIN=1)  and  output (fd=STDOUT=2):

As  seen, the main function is used in  its  complete  format,  accepting  argc as the number of arguments (parameters) from the shell, and argv as the list of lists of characters (strings), and returning an integer number to show the exit status. Since all the arguments from the shell to the main function of the program are characters, we have to convert them into equivalent numbers. We used the library routine atoi (ASCII to integer) as seen in line#7 and 8. Note that argv[0] is always the name of the program itself.

A sample run of the above program will be:

We know that shell is bootstrapping our program into the memory and making it a process. However, there is system function in library routine stdlib .h that allows executing any valid command string on a shell but from another program. This is similar to bash scripts, where we put the shell’s command lines in a script and give it to the shell for execution. But using system function, we do the same using C programming language. The following program bootstraps the above program using system function:

We compile and run this new program bootstrapper:

As seen, we ask the shell to bootstrap the system_bootstrap program that bootstraps the main_add program that sums two numbers (shell → system_bootstrap → main_add)

Are system_bootstrap and main_add programs executed under the same process, that is, have the same process ID? To answer this question, we can do a system call to the kernel and ask for the process IDs using getpid(), available in unistd .h header. We can change main_add and system_bootstrap program to print out their process IDs foremost and then continue with the rest of their instructions:

After rebuilding main_add and system_bootstrap programs, a sample run will output:

You see that their process IDs are different; they were executed under different processes. This means that in our UNIX-based/like system, we can run multiple processes simultaneously! This is contrary to our assumptions during our course. So far, we’ve assumed only one process can be executed in memory (besides the kernel and the shell.)

Wait! We still need the shell to bootstrap our system_bootstrap program.

Step 2. System Call to Bootstrap Program: exec

UNIX standard header, unistd .h, has 7 different variations of a system call to ask directly from the kernel to bootstrap a program. As we promised in class, we choose the one that works with the file descriptor; that is, we open the program file and give its file descriptor to the kernel to bootstrap the program. Here is an example:

The  main_add is  the  program  files  that  is  built  in previous  section.  As  seen  in  newargv variable,  we programmatically provide new arguments to the main_add program. Although we are supposed to provide 3 arguments, we have to provide an additional NULL argument (Why?) fexecve accepts a pointer to a copy of the environment variable table too, which we passed NULL for simplicity. The return value of exec system calls is nothing if successful, and -1 on error:

Wait a sec! If you closely look at the PIDs, they are the same. Here is why by our reference book:

When a process calls one of the exec functions (e.g., exec_bootstrap), that process is completely replaced by the new program (e.g., main_add), and the new program starts executing at its main function. The process ID does not change across an exec, because a new process is not created; exec merely replaces the current process its text, data, heap, and stack segments with a brand-new programfrom disk Advanced Programming in the UNIX Environment, Chapter 8, Section 10.

Note that we still need the shell to bootstrap the exec_bootstrap.

Step 3. A Program that Generates Program

We already know that we can create a new file by open() or creat() system calls. The new file can be a C program. Also, we know how to bootstrap another program using the system function or fexecve system call. So, we can bootstrap cc program to build a C program. Putting it all together, we can dynamically generate a program, build it, and run it using a bootstrapper.

Let’s write a bootstrapper using system function that generates a program for summing two numbers, builds it, runs it, and prints out the result:

As seen, we are creating the text body of a program inside another program. Please note the following:

1)  Newline character \n in the text body of the program should become normal text by \\n. Otherwise, it would be interpreted as the newline character in the bootstrapper program.

2)  The quotation in the text body of the program should become normal text by \” Otherwise, it would be interpreted as opening or closing quotation in the bootstrapper program.

The \ is called escape character, and we use it whenever we want to treat a character as a normal text, not as a

special character in C program.

Now, we can write the text body of the program into a file, build it by bootstrapping cc compiler using system

As seen in the last few lines, we:

1)  Create a new file for the program, called math .c, and we write the text body into it.

2)  We build it into the program file math using cc compiler using system function.

3)  We bootstrap the program using system function for 10 and 40.

Here is the result:

Step 4. Lab Assignment

You must redo step 2 considering the following conditions:

1)  The bootstrapper program should accept 3 arguments from a user:

a.   Math operation: + ,  - ,  * ,  /

b.   First operand

c.   Second operand

2)  The bootstrapper should generate a new body text for the program based on the user’s input values, build it, and run it using fexecve system call only. You are NOT allowed to use system function.

Note: You may get involved in a strange problem with executing your program file when replacing the two system() function with exec() system calls:

1) replacing the system() with a fexecve() for the C compiler (cc)

2) replacing the system() with a second fexecve() for executing the actual math program.              The second fexecve() never gets executed! Why? What is the workaround? Parent-childprocesses!

3)  For text manipulation or printing out the results, you can use library routines, e.g., string .h,  stdio .h.

A sample run of your final submission for operation on 10 and 30 would be:

A sample run of your final submission for / operation on 10 and 30 would be:

Note that the PID of the exec_math_bs and the PID of math programs are the same when using exec system calls. The sample code for steps 1 and 2 have been attached in a zip file named lab07_hfani .zip.

1.1. Deliverables

You will prepare and submit the program in one single zip file lab07_uwinid.zip containing the following items:

(90%) lab07_uwinid .zip

-  (70%) exec_math_bs .c => the bootstrapper builds and runs with no error for all 4 operations.

o (10%) if it builds successfully

o (20%) if it works for generating the math.c file

o (20%) if it works for the building the math.c using the child

o (20%) if it works for executing the math using parent

-  (20%) results .pdf/jpg/png => the image snapshot of the program run for all 4 operations

- (Optional) readme .txt

(10%) Files Naming and Formats

Please follow the naming convention as you lose marks otherwise. Instead of uwinid, use your own account name, e.g., mine is[email protected], so, lab07_hfani .zip