I am pretty new to both linux and c programming. I need to write a c code that creates two child processes, which is fine, but I need to further change the code of one of the child processes to "the code of a ls-command", and the other to "the code of the ps-command".
This is supposed to be a really simple "pseudo-code", but I am not really sure if I understand the question, any tips?
Sounds like fork() + execve() traditional combination. Call to fork() launches a new process which is a copy of the callee. And the consequent call to execve("ls") will replace the forked process with the content of the ls executable.
For more information see man 2 fork and man 3 execv.
Related
I was reading about processes and I came across this:
Usually, the child process then executes execve or a similar system call to change its memory image
what I can derive from this is this pseudocode:
if(child_created_sucessfully)
{
do_ABC_and_ignore_the_part_of_the_parent's_control_flow //is this what it meant to "change its memory image"?
}
(Question asked in the pseudocode's comment)
I completely don't understand this other part:
example, when a user types a command, say, sort, to the shell, the
shell forks off a child process and the child executes sort. The reason for this twostep
process is to allow the child to manipulate its file descriptors after the fork but
before the execve in order to accomplish redirection of standard input, standard
output, and standard error.
Regarding the first part
Usually, the child process then executes execve or a similar system
call to change its memory image
This simply means that when you create a child process it initializes it's own stack and heap memory although this is not 100% true. Since the new process is forked at time T at the time T + 1 when the process starts to run it is pretty much identical when it comes to the data in memory so there is a smart optimization called 'copy on write' more here.
Regarding the second part
example, when a user types a command, say, sort, to the shell, the
shell forks off a child process and the child executes sort. The
reason for this twostep process is to allow the child to manipulate
its file descriptors after the fork but before the execve in order to
accomplish redirection of standard input, standard output, and
standard error.
Simply put this means that when you execute a shell command (like ls, ps, grep, nstat...) the OS forks the current process which executes the command and the command itself is executed by this new process. An easy way to understand this is by using ps | grep ps this will first fork and create a new process, then this part comes to play
this twostep process is to allow the child to manipulate its file
descriptors after the fork but before the execve
and the standard output of the process is changed. After the new ps process executes the ps it will then fork and create one more process for the grep ps which will execute the grep and you should be able to see the ps process which created this grep process.
Is there a way to start a child process without fork(), using execvp() exclusively?
The pedantic answer to your question is no. The only system call that creates a new process is fork. The system call underlying execvp (called execve) loads a new program into an existing process, which is a different thing.
Some species of Unix have additional system calls besides fork (e.g. vfork, rfork, clone) that create a new process, but they are only small variations on fork itself, and none of them are part of the POSIX standard that specifies the functionality you can count on on anything that calls itself a Unix.
The slightly more helpful answer is that you might be looking for posix_spawn, which is a library routine wrapping fork and exec into a single operation, but I find it more troublesome to use that correctly than to write my own fork+exec subroutine. YMMV.
posix_spawn is the only posix compliant way to create a child process without calling fork directly. I say 'directly' because historically posix_spawn would itself just call fork, or vfork. However, that is no longer the case in GNU/linux. posix_spawn itself may be more efficient than fork, in addition to perhaps being a stronger fit conceptually when code is attempting to run a different executable.
If you aren't worried about portability, you can abandon posix and couple yourself directly to the kernel you are targeting. On linux the system call to create a child process is clone. At the time of this answer the manual page provides documentation for three variants, including the relatively new clone3.
I believe you can take the example from the manual page and add an execvp call to childFunc. I have not tried it yet, though!
Unlike Windows systems, where creating a new process and executing a new process image happen in a single step, Linux and other UNIX-like systems do them as two distinct steps.
The fork function makes an exact duplicate of the calling process and actually returns twice, once to the parent process and once to the child process. The execvp function (and other functions in the exec family) executes a new process image in the same process, overwriting the existing process image.
You can call execvp without calling fork first. If so, that just means the currently running program goes away and is replaced with the given program. However, fork is the way to create a new process.
As user zwol has already explained, execve() does not fork a new process. Rather, it replaces the address space and CPU state of current process,
loads the new address space from the executable filename and starts it from
main() with argument list argv and environment variable list envp.
It keeps pid and open files.
int execve(const char *filename,char *const argv [],char *const envp[]);
filename: name of executable file to run
argv: Command line arguments
envp: environment variable settings (e.g., $PATH, $HOME, etc.)
posix_spawn. But it ignores failures of execvp() -- potentially because implementing this was regarded as too complicated.
I have a question about exec() and fork() syscalls.
what I'm trying to get done: a little program where there are 3 "main" processes, one of them execute a fork() N times (user choice) and every child send messagges to the other 2 procs in order to sync and do some stuff.
So:
main.c: creates queue, sem and other ipc stuff. Then fork (2 times) and exec(p1)/(p2). If everything is ok, it starts to fork N times, on user choice.
p1.c: attach to ipc created by main, wait for messagges from one of the child of "main.c"
p2.c: attach to ipc... wait for messagges from one of the child of "main.c" or form "p2.c"
What i'm doing right now: I wrote 3 C files, each one with a main function, the "first main" reserve all IPC structure and then fork and execute and execve() in order to start the other 2 program.
Everything seems ok, the first one run and fork correctly, the execve() runs the other 2 programs and these can attach to ipc structure created by first program. Wonderful, but I have 3 program, 3 main and of course I cannot build only one executable file.
So my question: how can I load (if is possible) a program with syscall exec without a main?
If is not possibile, how should I write the structure of my program?
I hope is clear, if needed I can write the code, but right now there a few lines..
Thanks!!
Replace main by main_p1 and main_p2 and simply call them instead of calling exec.
exec* replaces the current process image with another new program. So those other programs must have a main if written in C.
You can fork your current process without calling exec* however. So you could link all three "programs" into one binary, and simply call into the other ones after forking.
I am looking for C code to use on a Linux based system to start another process asynchronously. The second process should continue, even if the first ends. I've looked through the "fork" and "system" and "exec" options, but don't see anything that will spawn a peer process that's not communicating with or a child of the original process.
Can this be done?
Certainly you can. In the parent fork() a child, and in that child first call daemon() (which is an easy way to avoid setsid etc.), then call something from the exec family.
In Linux (and Unix), every process is created by an existing process. You may be able to create a process using fork and then, kill the parent process. This way, the child will be an orphan but still, it gets adopted by init. If you want to create a process that is not inherited by another, I am afraid that may not be possible.
You do a fork (man 2 fork) followed by an execl (man 2 execl)
For creates a new process of the same image as the calling process (so a perfect twin), where execl replaces one of the twins with a new image.
If you search google for "fork execl" you will find many text book examples -- including how to use correctly fork() and exec()
The most common fork-execl you will still have the new process associated to the terminal -- to create a perfect background process you need to create what is called a daemon process -- the template for that can be fornd in this answer here Creating a daemon in Linux
I want to use gdb for looking into the various details of the fork() system call. To do this, I used one breakpoint at the fork() and from there onwards i am using step command but this way it is not working fine.
Can somebody explain me how to use gdb to look into every single step occuring during fork() system call?
Maybe you meant that you want to follow the child process instead of the parent once the fork is called? In that case:
If you want to follow the child
process instead of the parent process,
use the command set follow-fork-mode.
set follow-fork-mode mode
Set the debugger response to a program call of fork or vfork. A call
to fork or vfork creates a new
process. The mode argument can be:
parent: The original process is debugged after a fork. The child
process runs unimpeded. This is the
default.
child: The new process is debugged after a fork. The parent process runs
unimpeded.
If you want to see whats happening best if to look at the kernel code first, check it here.
I don't think you can single step through kernel from user space. You can use virtual server to do the debugging using KGDB. Check blog post here. Or you can use KGDB on main kernel.