1

Lets say i have run a simple background process which is:

sleep 25 &

I execute it on the command line as :

> sleep 25 &
[1] 26390
> ps
   PID TTY         TIME CMD
 26390 pts/52      0:00 sleep
  6746 pts/52      0:02 tcsh
 26391 pts/52      0:00 ps
> 

You can see that sleep is executing in the background with pid 26390 Now I try to do the same thing using c++.there are many different system calls to do it btw.

using system
using fork
using pipe

I tried below code:

if(p=fork()){
//Main process
cout<<p<<endl;
}
else{
execv("sleep 20 &",(char **)NULL);
}
}

output is:

> ./a.out
27391
> ps
   PID TTY         TIME CMD
  6746 pts/52      0:02 tcsh
 27392 pts/52      0:00 ps
> 

You can see that there is no sleep running in the background. Now i tried another way:

FILE* pipe = popen("sleep 20 &", "r");
    if(pipe){
                char buffer[128];
                while(fgets(buffer, 128, pipe));
                cout<<buffer<<endl;
                pclose(pipe);
             }

This hangs for 20 seconds and i will never get that cout printed with the process id.

> ./a.out

> 

Again I tried another way:

if(p=fork()){
//Main process
cout<<p<<endl;
}
else{
system("sleep 20 &");
}
}

> ./a.out
27464
> ps
   PID TTY         TIME CMD
 27466 pts/52      0:00 sleep
 27467 pts/52      0:00 ps
  6746 pts/52      0:02 tcsh

Now you can see sleep running in the background but with different PID.

But what i need is the actual pid of the sleep command that is executed in the background. I strongly believe that there should be some way to get the exact pid of the process running in the background in c++. Could anybody please help?

Vijay
  • 65,327
  • 90
  • 227
  • 319

4 Answers4

4

The process ID you are printing out is correct. The problem is that your sleep is not starting correctly.

There is no need to have a '&' in the arguments to sleep; your code is doing that already. If you do have the '&' the sleep is likely to complain because '&' is not a duration.

Try an exec call like this instead:

execlp("sleep", "sleep", "20", 0);

This searches the directories in PATH for a file called 'sleep', and replaces the current process with that process invoked with the arguments 'sleep' and '20'. These arguments are passed to main() using argv and argc.

Read the man page for exec for more details.

janm
  • 17,976
  • 1
  • 43
  • 61
1

The exec family of functions do not take shell commands, and they don't start shells. Instead they replace the process with one loaded from disk. The way you use the execv function it will fail.

The system function, on the other hand, actually starts a shell for the command(s) to run in.

The way to get the pid of a process is very simple: Use the getpid function. As in

std::cout << "pid = " << getpid() << '\n';

If you fork and use the above before a proper call to an exec function will show the pid of the process that sleeps. But not if you call system or popen, because those functions fork new processes themselves. Talking about system, if you put it in its own process, then you don't need to use & to run in the background, the child process itself makes sure the command is already in the background.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • @Vijay Call `getpid` like I've shown in my answer. *Then* call `exec`. – Some programmer dude Nov 22 '13 at 07:27
  • 1
    @JoachimPileborg Doing buffered I/O between a fork() and an exec() is a bad idea. Also, if you are doing fork() and exec(), the return value of fork() is the child PID, there is no need to call getpid() in the child. – janm Nov 22 '13 at 07:31
1

Read C shell considered harmful, then switch to a nice interactive shell (like zsh, fish, bash). For scripting, consider Posix sh (or use real scripting languages).

Read Advanced Linux Programming (most of it is valuable for other Unix systems, including Solaris).

You should learn how to use fork(2), getpid(2), execve(2), pipe(2), waitpid(2) etc... (these are standardized by POSIX). We can't take hours to teach you that, but you definitely should read books about them. Understanding how fork works is tricky.

You may want to call sleep(3) function or nanosleep(2) syscall. You should not use system or popen to sleep (both will fork a shell process, which is useless in that case), just call the function!

Don't forget that stdio(3) is buffered. You probably need to call fflush(3) (in C), or std::flush in C++, wisely (in particular before fork).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • @Basile.. Thanks for your suggestions. But I feel this is not the answer that i am expecting. I dont want you to teach me everything here. – Vijay Nov 22 '13 at 07:19
1

As others pointed out, the PID you showed for the sleep command is the PID of the sleep command itself (i.e. what you said you needed). So the PID you printed out from the process is 27464, and the PID of the sleep you created with system() is 27466. Perhaps if you say more about what you're trying to do we can be of more help.

Chris
  • 613
  • 6
  • 7