fork
#include <unistd.h>
pid_t fork(void);
返回值:
失败返回-1
成功子进程返回0,父进程返回子进程的id
进程调用fork,当控制转移到内核中,内核做如下的事情:
->分配新的内存块和内核数据结构给子进程
->将父进程部分数据结构内容拷贝给子进程
->添加子进程到系统进程列表中
->fork返回,开始调度器调度
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
pid_t pid = fork();
if(pid == -1)
{
perror("fork");
exit(1);
}
else if(pid == 0) //child
{
printf("this is child process!\n");
printf("child pid = %d, father pid = %d\n",getpid(),getppid());
}
else //father
{
printf("this is father process!\n");
printf("father pid = %d\n",getpid());
wait(NULL);
}
return 0;
}
fork调用失败的原因:
->系统中已经有太多进程了
->实际用户的进程数超过限制
->平台不支持
system
#include <stdlib.h>
int system(const char *command);
system()执行通过调用/bin/sh -c命令指定的命令,并在命令完成后返回,在执行命令的时候,SIGCHLD将被阻塞,SIGINT和SIGQUIT将被忽略。
参数:command
命令参数是指向包含shell命令行的以null结尾的字符串的指针。这个命令被传递给/bin/sh使用。
返回值:
fork()失败,返回-1
exec()失败,返回值相当于执行了exit(127)
参数command为NULL,返回1
system()调用bin/sh失败,返回127
成功返回shell的终止状态
popen
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
函数的作用是:通过创建一个管道、forking和调用shell来打开一个进程。由于管道是由定义单向的,类型参数只能指定读或写,而不是两者;生成的流相应地是只读的或只写的.
参数:command
命令参数是指向包含shell命令行的以null结尾的字符串的指针。这个命令被传递给/bin/sh使用。- c标志;解释,如果有的话,是由shell执行的。
type
是一个以NULL结尾的字符串指针, 包含'r'或者'w',在glibc 2.9以后,这个参数还可以包含 'e'
注意:默认情况下,输出popen()流被完全缓冲.
返回值:
如果fork(2)或pipe(2)调用失败,或者无法分配内存,popen()函数将返回NULL。
如果wait4(2)返回一个错误,或者检测到其他错误,那么pclose()函数返回-1。
在发生错误时,这些函数设置errnro来指示错误的原因。
如果内存分配失败,popen()函数不会设置errno。
如果底层的fork(2)或管道(2)失败,errno将被适当地设置。
如果类型参数无效,并且检测到该条件,errno将被设置为EINVAL。
如果pclose()无法获得子状态,则将errno设置为ECHILD。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
FILE* fp;
char buf[32];
if((fp = popen("cat aaa.txt","r")) == NULL)
{
perror("popen");
exit(1);
}
while(fgets(buf,32,fp) != NULL)
{
printf("%s",buf);
}
pclose(fp);
return 0;
}