27

I was wondering if there is some way to force to use some specific process ID to Linux to some application before running it. I need to know in advance the process ID.

slm
  • 15,396
  • 12
  • 109
  • 124
Borja Tarraso
  • 863
  • 2
  • 12
  • 20
  • 4
    Smells like an XY problem. Why do you need the pid in advance? –  Aug 08 '13 at 09:36
  • From what I know of Linux and Unices in general, I would be surprised if you could do that, but there are many ways to figure out the PID of a given process once it's running. Perhaps you should explain what you want to do and take suggestions on alternatives. – deStrangis Aug 08 '13 at 09:42
  • 2
    The short answer is no. – devnull Aug 08 '13 at 09:42
  • Do you really need to set the PID in advance, or would it be enough to communicate the opaquely generated PID to another process (e. g. from the return value of `fork` in the parent process or between `fork` and `exec*` in the child process or even after `exec*`)? – David Foerster Oct 18 '15 at 18:14
  • http://unix.stackexchange.com/questions/131514/run-a-process-to-particular-dedicated-pid-only – Ciro Santilli OurBigBook.com Dec 19 '15 at 14:55

7 Answers7

34

Actually, there is a way to do this. Since kernel 3.3 with CONFIG_CHECKPOINT_RESTORE set(which is set in most distros), there is /proc/sys/kernel/ns_last_pid which contains last pid generated by kernel. So, if you want to set PID for forked program, you need to perform these actions:

  1. Open /proc/sys/kernel/ns_last_pid and get fd
  2. flock it with LOCK_EX
  3. write PID-1
  4. fork

Voilà! Child will have PID that you wanted. Also, don't forget to unlock (flock with LOCK_UN) and close ns_last_pid.

You can checkout C code at my blog here.

Ruslan Kuprieiev
  • 845
  • 8
  • 11
9

As many already suggested you cannot set directly a PID but usually shells have facilities to know which is the last forked process ID.

For example in bash you can lunch an executable in background (appending &) and find its PID in the variable $!. Example:

$ lsof >/dev/null &
[1] 15458
$ echo $!
15458
7

On CentOS7.2 you can simply do the following:

Let's say you want to execute the sleep command with a PID of 1894.

sudo echo 1893 > /proc/sys/kernel/ns_last_pid; sleep 1000

(However, keep in mind that if by chance another process executes in the extremely brief amount of time between the echo and sleep command you could end up with a PID of 1895+. I've tested it hundreds of times and it has never happened to me. If you want to guarantee the PID you will need to lock the file after you write to it, execute sleep, then unlock the file as suggested in Ruslan's answer above.)

Kentgrav
  • 259
  • 3
  • 4
  • 1
    Keep in mind that `sudo echo 1893 > /proc/sys/kernel/ns_last_pid` will not work for non-root users because bash is the one that writes to the file, not `echo`. `echo 1893 | sudo tee /proc/sys/kernel/ns_last_pid` or running bash as root will both work. – TheTechRobo the Nerd Jul 14 '22 at 17:15
3

There's no way to force to use specific PID for process. As Wikipedia says:

Process IDs are usually allocated on a sequential basis, beginning at 0 and rising to a maximum value which varies from system to system. Once this limit is reached, allocation restarts at 300 and again increases. In Mac OS X and HP-UX, allocation restarts at 100. However, for this and subsequent passes any PIDs still assigned to processes are skipped

Oscerd
  • 1,616
  • 11
  • 14
  • Thanks for useful answers. Thing is I tried to generate some ICMP packet reply based on process ID, for this I need some checksum based on PID from the original process. So it is why I really to know in advance this PID in order to generate right checksum. It means, I should construct the packet based on request in real time. But this should be much easier and possible to prepare before if I know the PID. I assume the only option is to hack/modify linux source in order to gave specific PID in some particular case. – Borja Tarraso Aug 08 '13 at 10:30
  • You could start some processes in advance at boot time, and make them `execve` later the appropriate program (after having registered their pid in some well known places). I would definitely avoid hacking the kernel for this. – Basile Starynkevitch Aug 08 '13 at 10:50
  • Thanks, finally I will create the packet response in real time based on input packet. So I got the checksum based on process ID extracting from the original packet and giving some delay for the client application in order to have time to construct the packet and reply. This works perfectly to me now, so no any hack needed finally . – Borja Tarraso Aug 08 '13 at 11:15
2

You could just repeatedly call fork() to create new child processes until you get a child with the desired PID. Remember to call wait() often, or you will hit the per-user process limit quickly.

This method assumes that the OS assigns new PIDs sequentially, which appears to be the case eg. on Linux 3.3.

The advantage over the ns_last_pid method is that it doesn't require root permissions.

oliver
  • 6,204
  • 9
  • 46
  • 50
1

Every process on a linux system is generated by fork() so there should be no way to force a specific PID.

deagh
  • 2,647
  • 1
  • 30
  • 29
  • Except for the few processes magically started by the kernel: `/sbin/init` and perhaps `/sbin/modprobe` etc... (not to mention `vfork` as a variant of `fork`) – Basile Starynkevitch Aug 08 '13 at 10:48
1

From Linux 5.5 you can pass an array of PIDs to the clone3 system call to be assigned to the new process, up to one for each nested PID namespace, from the inside out. This requires CAP_SYS_ADMIN or (since Linux 5.9) CAP_CHECKPOINT_RESTORE over the PID namespace.

If you a not concerned with PID namespaces use an array of size one.

Timothy Baldwin
  • 3,551
  • 1
  • 14
  • 23