Linux进程学习笔记(二、创建进程)
2016-01-25 23:31
573 查看
fork()函数
一个现有的进程可以调用fork函数创建一个新进程#include <unistd.h> pid_t fork(void); //返回值:子进程返回0,父进程返回子进程的ID,若出错,返回-1
子进程对变量所做的改变不影响父进程中该变量的值,即父进程和子进程并不完全共享存储空间。
fork实例:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> int globvar = 6; char buf[] = "a write to stdout\n"; int main() { int var; pid_t pid; var = 88; if(write(STDOUT_FILENO, buf, sizeof(buf) -1) != sizeof(buf)-1) printf("write error\n!"); printf("Before fork \n"); if((pid = fork()) < 0) { printf("fork error"); }else if(pid == 0){ globvar++; var++; }else{ sleep(2); } printf("pid = %ld, globvar = %d, var = %d\n", (long)getpid(),globvar,var); exit(0); }
运行结果:
a write to stdout Before fork pid = 3214, globvar = 7, var = 89 pid = 3213, globvar = 6, var = 88
fork有以下两种用法:
(1)父进程希望复制自己,使父进程和子进程同时执行不同的代码段。常用于网络服务进程中–父进程等待客户端的服务请求。
(2)一个进程要执行一个不同的程序。在shell中常见,fork返回后立即调用exec。
vfork函数()
vfork函数的调用序列和返回值与fork相同,但两者语义不同。vfork函数用于创建一个新进程,该新进程的目的是exec一个新程序。
vfork与fork一样都创建一个子进程,但是它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec。
vfork与fork另一个区别是:vfork保证子进程先运行,在它调用exec或exit后父进程才可能被调度运行。
vfork实例:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int globvar = 6; int main(void) { int var; pid_t pid; var = 88; printf("before fork\n"); if((pid = vfork()) < 0) { printf("vfork error"); }else if(pid == 0) { globvar++; var++; _exit(0); } printf("pid = %ld, globvar = %d, var = %d\n", (long)getpid(), globvar, var); exit(0); }
运行结果:
before fork pid = 3329, globvar = 7, var = 89
改变了父进程的值,因为子进程在调用exit或exec之前是在父进程空间运行的。
system()函数
函数原型:#include <stdlib.h> int system(const char *cmdstring); //返回值:若cmdstring是空指针,返回非零值
因为system在实现中调用了fork,exec,和waitpid,因此有三种返回值
(1)fork失败或者waitpid返回除EINTR之外的出错,则system返回-1,并且设置errno以指示错误类型。
(2)如果exec失败,则其返回值如同shell执行了exit(127)一样(命令未找到)
(3)fork,exec,和waitpid都成功,那么system返回值是shell终止状态。
使用system而不是直接使用fork和exec的优点是:system进行了所需的各种出错处理以及各种信号处理
exec函数()
调用exec函数时,该进程执行的程序完全替换为新程序,而新程序从其main函数开始执行。因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用磁盘上的一个新程序替换了当前进程的正文段、数据段、堆段、栈段。
execl函数原型:
#include <unistd.h> int execl(const char *pathname, const char *arg0, ...); // 返回值:出错返回-1 成功不返回。
使用execl函数创建进程 实例
int execl(const char *path, const char *arg,...);
先创建
sum.c
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int sum; if(argc != 3) { printf("args error\n"); return -1; } sum = atoi(argv[1]) + atoi(argv[2]); printf("sum = %d\n", sum); return 0; }
gcc -o sum sum.c
生成sum
创建
exec.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { printf("start now \n"); execl("./sum","sum", "41", "34", NULL); printf("我是不会被执行的!\n"); return 0; }
gcc -o exec exec.c
生成
exec,执行
exec
yu@ubuntu:~/0125/fork$ ./exec start now sum = 75
printf("我是不会被执行的!\n");此句不会执行。
popen函数和pclose函数
函数原型:#include <stdio.h> FILE *popen(const char *comstring, const char *type); //返回值:成功返回文件指针;出错返回NULL int pclose(FILE *stream); //返回值:若成功,返回cmdstring的终止状态;出错返回-1
使用管道工作
这两个函数实现的操作是:创建一个管道,fork一个子进程,关闭未使用的管道端,执行一个shell命令,然后等待命令终止。
执行过程:
popen先执行fork,然后调用exec执行cmdstring,返回一个标准I/O文件指针
如果type是“r”,文件指针连接到cmdstring的标准输入
如果type是“w”,则文件指针连接到cmdstring的标准输入
//执行fp = popen(cmdstring, "r"); //父进程fp<--------------子进程cmdstring(stdout)
//执行fp = popen(cmdstring, "w"); //父进程fp-------------->子进程cmdstring(stdin)
pclose函数关闭标准I/O流,等待命令终止,然后返回shell的终止状态。
popen()函数用创建管道的方式启动一个进程, 并调用 shell. 因为管道是被定义成单向的,所以type参数只能定义成只读或者只写,不能是两者同时, 结果流也相应的是只读或者只写.
pclose等待新进程的结束,而不是杀新进程。
popen创建进程实例
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE *fp; fp = popen("ls -l", "r"); if(NULL == fp) { perror("popen"); return -1; } char buf[512]; bzero(buf,sizeof(buf)); int ret = fread(buf, 1, 512, fp); if(ret > 0) { printf("%s\n", buf); } return 0; }
gcc -o popen popen.c
./popen
运行结果
yu@ubuntu:~/0125/fork$ ./popen total 56 -rwxrwxr-x 1 yu yu 7544 Jan 25 05:23 a.out -rwxrwxr-x 1 yu yu 7364 Jan 25 06:22 exec -rw-rw-r-- 1 yu yu 196 Jan 25 06:22 exec.c -rw-rw-r-- 1 yu yu 510 Jan 25 04:55 fork.c -rwxrwxr-x 1 yu yu 7528 Jan 25 07:05 popen -rw-rw-r-- 1 yu yu 349 Jan 25 07:05 popen.c -rwxrwxr-x 1 yu yu 7400 Jan 25 06:20 sum -rw-rw-r-- 1 yu yu 230 Jan 25 06:20 sum.c -rw-rw-r-- 1 yu yu 112 Jan 25 04:55 temp.out -rw-rw-r-- 1 yu yu 418 Jan 25 05:22 vfork.c
相关文章推荐
- Linux系统下如何配置SSH?如何开启SSH?
- centos yum配置文件 .repo文件解释
- 基于tiny4412的Linux内核移植 -- SD卡驱动移植(五)
- VMware虚拟机 客户机是Linux的情况下客户机ping VMware网关,ping不通
- linux系统目录结构、用户和用户组管理
- CentOS linux修改主机名
- linux mysql-server和mysql-client
- Linux LVM(逻辑卷管理)
- linux 安装 ftp
- linux 程序自动运行总结
- linux基础常用命令
- CentOs 安装主意事项
- hadoop学习;大数据集在HDFS中存为单个文件;安装linux下eclipse出错解决;查看.class文件插件
- imx6q处理器,linux操作系统平台搭建 从eMMC启动系统
- imx6q处理器,linux操作系统平台搭建 从SD卡启动系统
- Linux + javaEE 学习笔记---Linux常用命令设定运行级别
- gpg keyserver
- Linux kernel release 4.4 中文翻译
- win10 与linux mint双系统 只能进入mint而无法进入windows的解决方案
- Linux第二天02