Win XP, C program: Query regarding int main() for child process - c

I am creating a child process and passing some arguments to it.
Now, the child process starts execution from the next line of code, but will I have to write another int main () separately for the child process, as below, or would it just use the already written code for int main() of the parent process?
createProcess(All required arguments);
if (pid == child_process)
{
int main ()
{
......
}
}
ENV: WinXP, VS2005
NOTE: The above code just describes the flow and may have syntax errors.

Are you confusing Windows CreateProcess with UNIX fork()? The two operating systems are different in the way that processes are created. With Windows you have to execute an exe file from the beginning, you can't continue as the child process after CreateProcess as you can with fork on UNIX. Your statement "the child process starts execution from the next line of code" is mistaken for Windows.
Mind you, your code would be illegal on UNIX as well, you can't have two functions called main, and you can't have nested functions in C.

Please read the documentation of CreateProcess() again.
The function takes the filename of the program to run in the new process. The nested function you're showing is not valid C.

Related

understanding overlaying process image and execl call

I want to build my own debugger, from scratch, so I am trying to pick up some of the concepts behind it. First, I am starting easy, using the ptrace library. But even at this point I am having some issues, let me run through this code:
int main(int argc, char** argv)
{
pid_t child_pid;
if (argc < 2) {
fprintf(stderr, "Expected a program name as argument\n");
return -1;
}
child_pid = fork();
if (child_pid == 0)
run_target(argv[1]);
else if (child_pid > 0)
run_debugger(child_pid);
else {
perror("fork");
return -1;
}
return 0;
}
this is nothing really special, I am creating a child process using fork()
the next function is what really I cannot understand
void run_target(const char* programname)
{
procmsg("target started. will run '%s'\n", programname);
/* Allow tracing of this process */
if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
perror("ptrace");
return;
}
/* Replace this process's image with the given program */
execl(programname, programname, 0);
}
The last call is the issue. this call represents the concept of overlaying process image.I am not fully getting what is happening. This is what the author says:
I've highlighted the part that interests us in this example. Note that the very next thing run_target does after ptrace is invoke the program given to it as an argument
with execl. This, as the highlighted part explains, causes the OS kernel to stop the process just before it begins executing the program in execl and send a signal to the parent.
To run the debugger basically the parent process must trace the child process, which acknowledges that it wants to be traced using PTRACEME. But I can’t figure out what that execl is doing. I can understand the purpose and the output but can’t figure out HOW. I consulted the man pages but could not wrap my head around this.
I would appreciate if someone could give me a clear explanation of what’s going on with this execl function.
I think you agree on this: the concept is that the debugger must debug program TARGET, that can only be debugged if it calls PTRACE_TRACEME.
Naturally, TARGET does not call ptrace with PTRACE_TRACEME argument in its source code.
So, the debugger must do it for it.
Initially, the debugger forks. At this time we have two processes:
Father: it calls run_debugger()
Child: it calls run_target()
Child is a process that the debugger has control on it, therefore it can call ptrace with argument PTRACE_TRACEME (in run_target()). But this process is not TARGET.
Thus, next step is associating to child the "image" of TARGET (namely the program we want to debug). A process image is an executable file required while executing the program, and it's composed of the 4 classical segments:
Code (text segment)
Data
Stack
Heap
execl and friends belong to exec family, namely functions which replace the current process image with a new process image. execl differs from its friend execv for the way the arguments are passed to the best of my knowledge, but the concept is the same.
So, what you need to know is that:
exec replaces the currently running program by another program (i..e., TARGET)
inside an EXISTING process.
The latter has called ptrace with argument PTRACE_TRACEME so the new program will not ignore the future ptrace calls made by the debugger.
If your question is the implementation details of exec systemcall, I have not a perfect knowledge for it, but I can give some suggestions:
Reading "The exec-like Functions" in the book "Understanding Linux Kernel"
Having a look to the source code (this question) directionates you to the source code of execve which is totally fine for you, same concept of execl.
If you want to create your own exec, this question can be useful as well.

how to call pkill in c program without using "system() library function"

In the below program, I've used system library function to execute "pkill" command. Is there any system call available for pkill(Because PID is unknown). I don't want to use "system" library function. Please let me know how to do it
#include <stdio.h>
int main()
{
char test[1024] = "pkill -15 radio";
system(test);
return 0;
}
The system call for sending signals to processes is kill; however, you need the process id for. If you intend to launch the program to be killed from within your application, too, use fork together with one of the exec-functions and you have it. Otherwise, you will most likely have to iterate over the /proc/* subdirectories.

Description and Working of Multiple Processes in C

I am new to multiple processes in C.
Once a new child process is created in C, what all code is copied to that processes.
I am confused as I am trying to create a child process but what would happen in its int main() function, since I am creating this child process from some other function.
I am working on Windows XP, VS2005.
I apologize for the confused question.
I would like to request for some documentation which would help me understand how to create and work with new processes in C
On Windows, you should have a look at the winapi CreateProcess() function which creates a new process that runs the command you want, also check this example in MSDN.

What is the purpose of fork()?

In many programs and man pages of Linux, I have seen code using fork(). Why do we need to use fork() and what is its purpose?
fork() is how you create new processes in Unix. When you call fork, you're creating a copy of your own process that has its own address space. This allows multiple tasks to run independently of one another as though they each had the full memory of the machine to themselves.
Here are some example usages of fork:
Your shell uses fork to run the programs you invoke from the command line.
Web servers like apache use fork to create multiple server processes, each of which handles requests in its own address space. If one dies or leaks memory, others are unaffected, so it functions as a mechanism for fault tolerance.
Google Chrome uses fork to handle each page within a separate process. This will prevent client-side code on one page from bringing your whole browser down.
fork is used to spawn processes in some parallel programs (like those written using MPI). Note this is different from using threads, which don't have their own address space and exist within a process.
Scripting languages use fork indirectly to start child processes. For example, every time you use a command like subprocess.Popen in Python, you fork a child process and read its output. This enables programs to work together.
Typical usage of fork in a shell might look something like this:
int child_process_id = fork();
if (child_process_id) {
// Fork returns a valid pid in the parent process. Parent executes this.
// wait for the child process to complete
waitpid(child_process_id, ...); // omitted extra args for brevity
// child process finished!
} else {
// Fork returns 0 in the child process. Child executes this.
// new argv array for the child process
const char *argv[] = {"arg1", "arg2", "arg3", NULL};
// now start executing some other program
exec("/path/to/a/program", argv);
}
The shell spawns a child process using exec and waits for it to complete, then continues with its own execution. Note that you don't have to use fork this way. You can always spawn off lots of child processes, as a parallel program might do, and each might run a program concurrently. Basically, any time you're creating new processes in a Unix system, you're using fork(). For the Windows equivalent, take a look at CreateProcess.
If you want more examples and a longer explanation, Wikipedia has a decent summary. And here are some slides here on how processes, threads, and concurrency work in modern operating systems.
fork() is how Unix create new processes. At the point you called fork(), your process is cloned, and two different processes continue the execution from there. One of them, the child, will have fork() return 0. The other, the parent, will have fork() return the PID (process ID) of the child.
For example, if you type the following in a shell, the shell program will call fork(), and then execute the command you passed (telnetd, in this case) in the child, while the parent will display the prompt again, as well as a message indicating the PID of the background process.
$ telnetd &
As for the reason you create new processes, that's how your operating system can do many things at the same time. It's why you can run a program and, while it is running, switch to another window and do something else.
fork() is used to create child process. When a fork() function is called, a new process will be spawned and the fork() function call will return a different value for the child and the parent.
If the return value is 0, you know you're the child process and if the return value is a number (which happens to be the child process id), you know you're the parent. (and if it's a negative number, the fork was failed and no child process was created)
http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html
fork() is basically used to create a child process for the process in which you are calling this function. Whenever you call a fork(), it returns a zero for the child id.
pid=fork()
if pid==0
//this is the child process
else if pid!=0
//this is the parent process
by this you can provide different actions for the parent and the child and make use of multithreading feature.
fork() will create a new child process identical to the parent. So everything you run in the code after that will be run by both processes — very useful if you have for instance a server, and you want to handle multiple requests.
System call fork() is used to create processes. It takes no arguments and returns a process ID. The purpose of fork() is to create a new process, which becomes the child process of the caller. After a new child process is created, both processes will execute the next instruction following the fork() system call. Therefore, we have to distinguish the parent from the child. This can be done by testing the returned value of fork():
If fork() returns a negative value, the creation of a child process was unsuccessful.
fork() returns a zero to the newly created child process.
fork() returns a positive value, the process ID of the child process, to the parent. The returned process ID is of type pid_t defined in sys/types.h. Normally, the process ID is an integer. Moreover, a process can use function getpid() to retrieve the process ID assigned to this process.
Therefore, after the system call to fork(), a simple test can tell which process is the child. Please note that Unix will make an exact copy of the parent's address space and give it to the child. Therefore, the parent and child processes have separate address spaces.
Let us understand it with an example to make the above points clear. This example does not distinguish parent and the child processes.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#define MAX_COUNT 200
#define BUF_SIZE 100
void main(void)
{
pid_t pid;
int i;
char buf[BUF_SIZE];
fork();
pid = getpid();
for (i = 1; i <= MAX_COUNT; i++) {
sprintf(buf, "This line is from pid %d, value = %d\n", pid, i);
write(1, buf, strlen(buf));
}
}
Suppose the above program executes up to the point of the call to fork().
If the call to fork() is executed successfully, Unix will make two identical copies of address spaces, one for the parent and the other for the child.
Both processes will start their execution at the next statement following the fork() call. In this case, both processes will start their execution at the assignment
pid = .....;
Both processes start their execution right after the system call fork(). Since both processes have identical but separate address spaces, those variables initialized before the fork() call have the same values in both address spaces. Since every process has its own address space, any modifications will be independent of the others. In other words, if the parent changes the value of its variable, the modification will only affect the variable in the parent process's address space. Other address spaces created by fork() calls will not be affected even though they have identical variable names.
What is the reason of using write rather than printf? It is because printf() is "buffered," meaning printf() will group the output of a process together. While buffering the output for the parent process, the child may also use printf to print out some information, which will also be buffered. As a result, since the output will not be send to screen immediately, you may not get the right order of the expected result. Worse, the output from the two processes may be mixed in strange ways. To overcome this problem, you may consider to use the "unbuffered" write.
If you run this program, you might see the following on the screen:
................
This line is from pid 3456, value 13
This line is from pid 3456, value 14
................
This line is from pid 3456, value 20
This line is from pid 4617, value 100
This line is from pid 4617, value 101
................
This line is from pid 3456, value 21
This line is from pid 3456, value 22
................
Process ID 3456 may be the one assigned to the parent or the child. Due to the fact that these processes are run concurrently, their output lines are intermixed in a rather unpredictable way. Moreover, the order of these lines are determined by the CPU scheduler. Hence, if you run this program again, you may get a totally different result.
You probably don't need to use fork in day-to-day programming if you are writing applications.
Even if you do want your program to start another program to do some task, there are other simpler interfaces which use fork behind the scenes, such as "system" in C and perl.
For example, if you wanted your application to launch another program such as bc to do some calculation for you, you might use 'system' to run it. System does a 'fork' to create a new process, then an 'exec' to turn that process into bc. Once bc completes, system returns control to your program.
You can also run other programs asynchronously, but I can't remember how.
If you are writing servers, shells, viruses or operating systems, you are more likely to want to use fork.
Multiprocessing is central to computing. For example, your IE or Firefox can create a process to download a file for you while you are still browsing the internet. Or, while you are printing out a document in a word processor, you can still look at different pages and still do some editing with it.
Fork creates new processes. Without fork you would have a unix system that could only run init.
Fork() is used to create new processes as every body has written.
Here is my code that creates processes in the form of binary tree.......It will ask to scan the number of levels upto which you want to create processes in binary tree
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
int main()
{
int t1,t2,p,i,n,ab;
p=getpid();
printf("enter the number of levels\n");fflush(stdout);
scanf("%d",&n);
printf("root %d\n",p);fflush(stdout);
for(i=1;i<n;i++)
{
t1=fork();
if(t1!=0)
t2=fork();
if(t1!=0 && t2!=0)
break;
printf("child pid %d parent pid %d\n",getpid(),getppid());fflush(stdout);
}
waitpid(t1,&ab,0);
waitpid(t2,&ab,0);
return 0;
}
OUTPUT
enter the number of levels
3
root 20665
child pid 20670 parent pid 20665
child pid 20669 parent pid 20665
child pid 20672 parent pid 20670
child pid 20671 parent pid 20670
child pid 20674 parent pid 20669
child pid 20673 parent pid 20669
First one needs to understand what is fork () system call. Let me explain
fork() system call creates the exact duplicate of parent process, It makes the duplicate of parent stack, heap, initialized data, uninitialized data and share the code in read-only mode with parent process.
Fork system call copies the memory on the copy-on-write basis, means child makes in virtual memory page when there is requirement of copying.
Now Purpose of fork():
Fork() can be used at the place where there is division of work like a server has to handle multiple clients, So parent has to accept the connection on regular basis, So server does fork for each client to perform read-write.
fork() is used to spawn a child process. Typically it's used in similar sorts of situations as threading, but there are differences. Unlike threads, fork() creates whole seperate processes, which means that the child and the parent while they are direct copies of each other at the point that fork() is called, they are completely seperate, neither can access the other's memory space (without going to the normal troubles you go to access another program's memory).
fork() is still used by some server applications, mostly ones that run as root on a *NIX machine that drop permissions before processing user requests. There are some other usecases still, but mostly people have moved to multithreading now.
The rationale behind fork() versus just having an exec() function to initiate a new process is explained in an answer to a similar question on the unix stack exchange.
Essentially, since fork copies the current process, all of the various possible options for a process are established by default, so the programmer does not have supply them.
In the Windows operating system, by contrast, programmers have to use the CreateProcess function which is MUCH more complicated and requires populating a multifarious structure to define the parameters of the new process.
So, to sum up, the reason for forking (versus exec'ing) is simplicity in creating new processes.
Fork() system call use to create a child process. It is exact duplicate of parent process. Fork copies stack section, heap section, data section, environment variable, command line arguments from parent.
refer: http://man7.org/linux/man-pages/man2/fork.2.html
Fork() was created as a way to create another process with shared a copy of memory state to the parent. It works the way it does because it was the most minimal change possible to get good threading capabilities in time-slicing mainframe systems that previously lacked this capability. Additionally, programs needed remarkably little modification to become multi-process, fork() could simply be added in the appropriate locations, which is rather elegant. Basically, fork() was the path of least resistance.
Originally it actually had to copy the entire parent process' memory space. With the advent of virtual memory, it has been hacked and changed to be more efficient, with copy-on-write mechanisms avoiding the need to actual copy any memory.
However, modern systems now allow the creation of actual threads, which simply share the parent process' actual heap. With modern multi-threading programming paradigms and more advanced languages, it's questionable whether fork() provides any real benefit, since fork() actually prevents processes from communicating through memory directly, and forces them to use slower message passing mechanisms.

How do you spawn another process in C?

How do you run an external program and pass it command line parameters using C? If you have to use operating system API, include a solution for Windows, Mac, and Linux.
It really depends on what you're trying to do, exactly, as it's:
OS dependent
Not quite clear what you're trying to do.
Nevertheless, I'll try to provide some information for you to decide.
On UNIX, fork() creates a clone of your process from the place where you called fork. Meaning, if I have the following process:
#include <unistd.h>
#include <stdio.h>
int main()
{
printf( "hi 2 u\n" );
int mypid = fork();
if( 0 == mypid )
printf( "lol child\n" );
else
printf( "lol parent\n" );
return( 0 );
}
The output will look as follows:
hi 2 u
lol child
lol parent
When you fork() the pid returned in the child is 0, and the pid returned in the parent is the child's pid. Notice that "hi2u" is only printed once... by the parent.
execve() and its family of functions are almost always used with fork(). execve() and the like overwrite the current stackframe with the name of the application you pass to it. execve() is almost always used with fork() where you fork a child process and if you're the parent you do whatever you need to keep doing and if you're the child you exec a new process. execve() is also almost always used with waitpid() -- waitpid takes a pid of a child process and, quite literally, waits until the child terminates and returns the child's exit status to you.
Using this information, you should be able to write a very basic shell; one that takes process names on the command line and runs processes you tell it to. Of course, shells do more than that, like piping input and output, but you should be able to accomplish the basics using fork(), execve() and waitpid().
NOTE: This is *nix specific! This will NOT work on Windows.
Hope this helped.
If you want to perform more complicated operations, like reading the output of the external program, you may be better served by the popen system call. For example, to programmatically access a directory listing (this is a somewhat silly example, but useful as an example), you could write something like this:
#include <stdio.h>
int main()
{
int entry = 1;
char line[200];
FILE* output = popen("/usr/bin/ls -1 /usr/man", "r");
while ( fgets(line, 199, output) )
{
printf("%5d: %s", entry++, line);
}
}
to give output like this
1: cat1
2: cat1b
3: cat1c
4: cat1f
5: cat1m
6: cat1s
...
#include <stdlib.h>
int main()
{
system("echo HAI");
return 0;
}
I want to give a big warning to not use system and 100% never use system when you write a library. It was designed 30 years ago when multithreading was unknown to the toy operating system called Unix. And it is still not useable even when almost all programs are multithreaded today.
Use popen or do a fork+execvp, all else is will give you hard to find problems with signal handling, crashs in environment handling code etc. It's pure evil and a shame that the selected and most rated answer is promoting the use of "system". It's more healthy to promote the use of Cocain on the workplace.
On UNIX, I think you basically need to fork it if you want the spawned process to run detached from your the spawing one : For instance if you don't want your spawned process to be terminate when you quit your spawning process.
Here is a page that explains all the subtle differences between Fork, System, Exec.
If you work on Win,Mac and linux, I can recommend you the Qt Framework and its QProcess object, but I don't know if that's an option for you. The great advantages is that you will be able to compile the same code on windows linux and mac :
QString program = "./yourspawnedprogram";
QProcess * spawnedProcess = new QProcess(parent);
spawnedProcess->start(program);
// or spawnedProcess->startDetached(program);
And for extra, you can even kill the child process from the mother process,
and keep in communication with it through a stream.
One solution is the system function defined in stdlib.h
int system(const char *string);
system api example
If you need to check/read/parse the output of your external command, I would suggest to use popen() instead of system().
Speaking of platform-dependent recipes, on Windows use CreateProcess, on Posix (Linux, Mac) use fork + execvp. But system() should cover your basic needs and is part of standard library.

Resources