Linux c进程管理—创建进程 system、execl、execlp、fork
Linux c 进程管理: 1. 创建进程: system函数: int system(const char*filename); 建立独立进程,拥有独立的代码空间,内存空间 等待新的进程执行完毕,system才返回.(阻塞) system:创建一个堵塞的新进程,新进程结束后,system才返回 案例: 使用system调用一个程序。 观察进程ID。 观察阻塞。 代码: text.c #include<stdio.h> #include<unistd.h> void main() { printf(“%d\n”,getpid()); //打印当前进程id sleep(10); //进程睡眠10秒 } gcctext.c –o text system.c #include<stdio.h> #include<stdlib.h> #include<unistd.h> void main() { printf(“%d\n”,getpid()); int r=system(“./text”); printf(“%d\n”,r); } gccsystem.c –o main 结论: 新进程的返回值与system返回值有关系。 任何进程的返回值:不要超过255。一个字节。 system的返回值中8-15位存放返回码(一个字节存放返回码) 要想得到返回码,则不能直接用system的返回值,要取返回值的8-15位的内容。 Linux提供一个宏来获取该值WEXITSTATUS(status)、包含在#include<sys/wait.h>中 代码: text.c #include<stdio.h> #include<unistd.h> int main() { printf(“%d\n”,getpid()); //打印当前进程id sleep(10); //进程睡眠10秒 return 99; } gcctext.c –o text system.c #include<stdio.h> #include<stdlib.h> #include<unistd.h> void main() { printf(“%d\n”,getpid()); int r=system(“./text”); printf(“%d\n”,WEXITSTATUS(r)); } gccsystem.c –o main popen函数: #include<stdio.h> 函数原型: FILE * popen ( constchar * command , const char * type ); int pclose ( FILE * stream ); popen:创建子进程 在父子进程之间建立一个管道 command: 是一个指向以 NULL 结束的 shell 命令字符串的指针。这行命令将被传到 bin/sh 并使用 -c 标志,shell将执行这个命令。 type: 只能是读或者写中的一种,得到的返回值(标准I/O 流)也具有和 type 相应的只读或只写类型。如果type 是 “r” 则文件指针连接到 command 的标准输出;如果 type 是 “w” 则文件指针连接到command 的标准输入。 返回值: 如果调用成功,则返回一个读或者打开文件的指针,如果失败,返回NULL,具体错误要根据errno判断 int pclose (FILE*stream) 参数说明: stream:popen返回的文件指针 返回值: 如果调用失败,返回 -1 案例: 使用popen调用ls -l,并且建立一个管道读取输出 #include<stdio.h> #include<unistd.h> void main() { char buf[1024]; FILE *f=popen(“ls - l”,”r”); int fd=fileno(f); int r; while((r=read(fd,buf,1024))>0) { buf[r]=0; printf(“%s”,buf); } close(fd); pclose(f); } execlexecle: 代替当前进程的代码空间中的代码数据,函数本身不创建新的进程。 excel函数: int execl(const char * path,const char*arg,….); 第一个参数:替换的程序 第二个参数…..:命令行 命令行格式:命令名 选项参数 命令行结尾必须空字符串结尾 案例: 使用exec执行一个程序。 体会:*是否创建新的进程?没有 *体会execl的参数的命令行的格式 *体会execl与execlp的区别(execl只当前路径)(不是当前路径必须加绝对路径) execlp使用系统的搜索路径 *体会execl替换当前进程的代码 代码: text.c #include<stdio.h> #include<unistd.h> void main() { printf(“%d\n”,getpid()); //打印当前进程id sleep(10); //进程睡眠10秒 } gcctext.c –o text exec.c #include<stdio.h> #include<unistd.h> void main() { printf(“main::%d\n”,getpid()); int r=excel(“./text”,”text”,NULL); //int r=excel(“/bin/ls”,”ls”,”-l”,NULL); //int r=excelp(“ls”,”ls”,”-l”,NULL); printf(“结束:%d\n”,r); } 总结: 程序运行后,两个打印进程id是一样,则excel和execlp不创建新的进程。 最后的打印结束的语句不能执行,因为excel和excelp是将新的程序的代码替换到该程序的代码空间中了。 两个函数的最后一个参数必须为0或NULL 函数的第一个参数是可执行程序的路径,第二个参数才是执行的命令 fork函数: 函数原型: pid_t fork(); //1.创建进程 //2.新进程的代码是什么:克隆父进程的代码 而且克隆了执行的位置.(从父进程复制过来的代码,fork之前的代码不会再子进程中执行,子进程只会执行从父进程复制过来的fork以后的代码) //3.在子进程不调用fork所以返回值=0;(pid=0为子进程的) //4.父子进程同时执行. 例子代码: #include<stdio.h> #include<unistd.h> void main() { printf(“创建进程之前\n”); int pid=fork(); printf(“创进程之后%d\n”,pid); } 虽然子进程的代码是克隆父进程的,但我们也可以把子进程要执行的代码和父进程要执行的代码分开。 例子: #include<stdio.h> #include<unistd.h> voidmain() { printf(“创建进程之前:\n”); int pid=fork(); if(pid==0) { printf(“子进程:\n”); } else { printf(“父进程:\n”); } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。