Chinaunix首页 | 论坛 | 博客
  • 博客访问: 139129
  • 博文数量: 21
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 233
  • 用 户 组: 普通用户
  • 注册时间: 2013-03-17 15:31
个人简介

学习中。。

文章分类

全部博文(21)

文章存档

2015年(1)

2014年(17)

2013年(3)

我的朋友

分类: LINUX

2014-05-01 11:19:44

linux下fork和exec实例


    在这里主要通过例子介绍fork与exec如何使用,即所谓的进程控制。如果想要了解一些关于进程的基本知识,如
的知识,请自己点击链接。其实原文的解析是相当精彩的,如果有耐心的朋友可以点击查看。
    第一部分:fork实战。实例代码如下,如想实战可点这里下载


#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    pid_t pid;
    char* message;
    int n;
    pid = fork();
    if (pid < 0)
    {
        perror("fork failed\n");
        exit(1);
    }
    if (pid == 0)
    {
        message = "this is child \n";
        = 6;
    }
    else {
        message = "this is the parent\n";
        = 3;
    }
    for (; n>0;n--)
    {
        printf(message);
        sleep(1);
    }
    return 0;
}


我们执行以下命令:
$ gcc -g ex_fork.c
$ ./ex_fork

得到的结果如下所示:
xiaolluo@ubuntu:~/workspace$ gcc -g -o ex_fork ex_fork.c
ex_fork.c: In function ‘main’:
ex_fork.c:28: warning: format not a string literal and no format arguments
xiaolluo@ubuntu:~/workspace$ ./ex_fork
this is the parent
this is child
this is the parent
this is child
this is the parent
this is child
this is child
xiaolluo@ubuntu:~/workspace$ this is child
this is child

实际上程序的运行过程如下图所示

http://blog.chinaunix.net/photo/119919_101020145706.png

解析:
1)fork函数的特点概括起来就是“一次调用,两次返回“, 同样是pid = fork()执行过后,右边(子进程)的pid=0, 而左边(父进程)pid的值等于子进程的id,是一个大于0的数。
2)在语句 pid = fork()之后,子进程被创建,子进程除了pid之外完全与父进程相同,因为数据是通过复制的方法从父进程赋予子进程的,之后的操作,互不影响。这里就很好地体现了函数命fork(分叉)的含义了。
3)可以在gdb中输入以下命令来设置gdb在fork之后跟踪子进程: set follow-fork-mode child (在run命令之前输入)

    第二部分:exec函数实战
exec函数介绍:
    用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。
exec*的函数原型如下:
   

#include <unistd.h>

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);


我只介绍execl的使用,代码如下,如想实践一下可点这里下载



#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int fd;
    if (argc != 2) {
        fputs("usage: wrapper file\n", stderr);
        exit(1);
    }
    fd = open(argv[1], O_RDONLY);
    if(fd<0) {
        perror("open");
        exit(1);
    }
    dup2(fd, STDIN_FILENO);
    close(fd);
    execl("./upper", "upper", NULL);
    perror("exec ./upper");
    exit(1);
}




#include <ctype.h>
#include <stdio.h>

int main(void)
{
    int ch;
    while((ch = getchar()) != EOF) {
        putchar(toupper(ch));
    }
    return 0;
}


执行以下命令:
$ vim file.txt (输入任意小写字母并保存)
$ gcc -g -o upper upper.c
$ gcc -g -o wrapper wrapper.c
$ cat file.txt
$ ./wrapper file.txt

我执行后得到的结果是:
xiaolluo@ubuntu:~/workspace$ vim file.txt
xiaolluo@ubuntu:~/workspace$ gcc -g -o upper upper.c
xiaolluo@ubuntu:~/workspace$ gcc -g -o wrapper wrapper.c
xiaolluo@ubuntu:~/workspace$ cat file.txt
this is some words in low case and we want the program to change them to upper
case .
xiaolluo@ubuntu:~/workspace$ ./wrapper file.txt
THIS IS SOME WORDS IN LOW CASE AND WE WANT THE PROGRAM TO CHANGE THEM TO UPPER
CASE .
xiaolluo@ubuntu:~/workspace$

解释:
1)upper.c的作用是将标准输入的缓存中的数据以大写的形式打印在屏幕上。
2)wrapper.c的作用是利用函数dup2(fd, STDIN_FILENO)重定向标准输入,然后用execl函数执行upper程序。

原文连接:http://blog.sina.com.cn/s/blog_7c60861501018t18.html
阅读(2359) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~