linux编程实践:如何在一个程序的内部启动另一个程序?
我们可以在一个进程的内部启动另一个程序,从而创建一个新的进程。这个工作可以通过库函数的system来完成,可以‘ man 3 system’获取帮助。
#include<stdlib.h> #include<stdio.h> int main(){ printf("Running ps with system\n"); system("ps ax"); printf("Done.\n"); exit(0); }
编译“systeml.c”文件,运行:
root@iZ2zecwg27cog23tyl7z4eZ:~/pro# ./systeml Running ps with system PID TTY STAT TIME COMMAND 1 ? Ss 0:04 /sbin/init noibrs splash 2 ? S 0:00 [kthreadd] 4 ? I< 0:00 [kworker/0:0H] 6 ? I< 0:00 [mm_percpu_wq] 7 ? S 0:02 [ksoftirqd/0] 8 ? I 1:07 [rcu_sched] 9 ? I 0:00 [rcu_bh] 10 ? S 0:00 [migration/0] 11 ? S 0:02 [watchdog/0] 12 ? S 0:00 [cpuhp/0] 13 ? S 0:00 [kdevtmpfs] 14 ? I< 0:00 [netns] 15 ? S 0:00 [rcu_tasks_kthre] 16 ? S 0:00 [kauditd] 17 ? S 0:00 [khungtaskd] 18 ? S 0:00 [oom_reaper] 19 ? I< 0:00 [writeback] 20 ? S 0:00 [kcompactd0] 21 ? SN 0:00 [ksmd] 22 ? I< 0:00 [crypto] 23 ? I< 0:00 [kintegrityd] 24 ? I< 0:00 [kblockd] 25 ? I< 0:00 [ata_sff] 26 ? I< 0:00 [md] 27 ? I< 0:00 [edac-poller] 28 ? I< 0:00 [devfreq_wq] 29 ? I< 0:00 [watchdogd] 31 ? I 0:14 [kworker/0:1] 33 ? S 0:00 [kswapd0] 34 ? I< 0:00 [kworker/u3:0] 35 ? S 0:00 [ecryptfs-kthrea] 77 ? I< 0:00 [kthrotld] 78 ? I< 0:00 [acpi_thermal_pm] 79 ? S 0:00 [scsi_eh_0] 80 ? I< 0:00 [scsi_tmf_0] 81 ? S 0:00 [scsi_eh_1] 82 ? I< 0:00 [scsi_tmf_1] 88 ? I< 0:00 [ipv6_addrconf] 97 ? I< 0:00 [kstrp] 114 ? I< 0:00 [charger_manager] 152 ? I 0:00 [kworker/0:2] 153 ? I< 0:01 [kworker/0:1H] 173 ? S 0:01 [jbd2/vda1-8] 174 ? I< 0:00 [ext4-rsv-conver] 209 ? S<s 0:03 /lib/systemd/systemd-journald 250 ? Ss 0:00 /lib/systemd/systemd-udevd 271 ? Ss 0:00 /lib/systemd/systemd-networkd 294 ? Ss 0:02 /lib/systemd/systemd-resolved 336 ? Ss 0:01 /usr/sbin/cron -f 337 ? Ssl 7:36 /usr/sbin/aliyun-service 341 ? Ss 0:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --syst 351 ? Ss 0:00 /lib/systemd/systemd-logind 388 ? Ssl 0:00 /usr/bin/python3 /usr/bin/networkd-dispatcher --run-startup-triggers 389 ? Ss 0:00 /usr/sbin/atd -f 390 ? Ssl 6:02 /usr/local/aegis/aegis_update/AliYunDunUpdate 391 ? Ssl 0:15 /usr/lib/accountsservice/accounts-daemon 394 ? Ssl 0:00 /usr/sbin/rsyslogd -n 402 ? I< 0:00 [ttm_swap] 452 ? S 0:03 /usr/sbin/chronyd 501 ttyS0 Ss+ 0:00 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyS0 vt220 505 ? S<sl 53:20 /usr/local/aegis/aegis_client/aegis_10_65/AliYunDun 506 tty1 Ss 0:00 /bin/login -p -- 649 ? Ss 0:00 /usr/sbin/sshd -D 683 ? Ss 0:00 /lib/systemd/systemd --user 684 ? S 0:00 (sd-pam) 694 tty1 S+ 0:00 -bash 921 ? I 0:00 [kworker/u2:2] 965 ? Ss 0:00 sshd: root@pts/0 1007 pts/0 Ss 0:00 -bash 1130 ? Ss 0:00 sshd: root@pts/1 1169 pts/1 Ss+ 0:00 -bash 1182 ? I 0:00 [kworker/u2:1] 1230 pts/0 S+ 0:00 ./systeml 1231 pts/0 S+ 0:00 sh -c ps ax 1232 pts/0 R+ 0:00 ps ax Done. root@iZ2zecwg27cog23tyl7z4eZ:~/pro#
我们再来看一个创建进程的底层接口exec,“man 3 exec”获取帮助。
我们可以调用fork创建一个新进程,“man 2 fork”获取更多帮助信息。
简单的例子“forkl.c”
#include <sys/types.h> #include <unistd.h> #include<stdio.h> #include<stdlib.h> int main(){ pid_t pid; char *message; int n; printf("fork program starting....\n"); pid=fork(); switch(pid){ case -1: perror("fork failed"); exit(1); case 0: message="This is the child"; n=5; break; default: message="This is the parent"; n=3; break; } for(;n>0;n--){ puts(message); sleep(1); } exit(0); }
当fork启动一个子进程时,子进程就有了它自己的生命周期并将独立运行。有时我们希望知道子进程何时结束。所以我们可以通过在父进程中调用wait函数,让父进程等待子进程的结束。参考“man 2 wait”获取更多信息。
还有另一个系统调用,可以用来等待子进程的结束,它就是waitpid函数,你可以用它来等待某个特定进程的结束。
REF:
C 库函数 – freopen() | 菜鸟教程 https://www.runoob.com/cprogramming/c-function-freopen.html