linux多进程编程

一、进程的概念
       首先了解,什么是进程?

Linux 操作系统是面向多用户的.在同一时间可以有许多用户向操作系统发出各种命令.那么操作系统是怎么实现多用户的环境呢? 在现代的操作系统里面都有程序和进程的概念那么什么是程序,什么是进程呢? 通俗的讲程序是一个包含可以执行代码的文件,是一个静态的文件而进程是一个开始执行但是还没有结束的程序的实例.就是可执行文件的具体实现.一个程序可能有许多进程,而每一个进程又可以有许多子进程.依次循环下去而产生子孙进程当程序被系统调用到内存以后,系统会给程序分配一定的资源(内存,设备等等)然后进行一系列的复杂操作使程序变成进程以供系统调用在系统里面只有进程没有程序为了区分各个不同的进程,系统给每一个进程分配了一个ID(就象我们的身份证)以便识别为了充分的利用资源,系统还对进程区分了不同的状态将进程分为新建运行阻塞就绪和完成五个状态新建表示进程正在被创建运行是进程正在运行阻塞是进程正在等待某一个事件发生就绪是表示系统正在等待CPU 来执行命令而完成表示进程已经结束了系统正在回收资源

二、进程的标志
       明白了什么是进程,接下来要了解进程的标志。

   上面我们知道了进程都有一个ID,那么我们怎么得到进程的ID ?系统调用getpid 以得到进程的ID,getppid 可以得到父进程(创建调用该函数进程的进程)ID.

#include <unistd>;

pid_t getpid(void);

pid_t getppid(void);

进程是为程序服务的而程序是为了用户服务的系统为了找到进程的用户名还为进程和用户建立联系这个用户称为进程的所有者相应的每一个用户也有一个用户ID通过系统调用getuid 可以得到进程的所有者的ID由于进程要用到一些资源Linux 对系统资源是进行保护的为了获取一定资源进程还有一个有效用户ID这个ID 和系统的资源使用有关涉及到进程的权限.通过系统调用geteuid 我们可以得到进程的有效用户ID.和用户ID相对应进程还有一个组ID 和有效组ID 系统调用getgid getegid 可以分别得到组ID 和有效组ID

三、进程的创建
      学习如何创建进程!    

   创建一个进程的系统调用很简单.我们只要调用fork 函数就可以了.

    #include <unistd.h>;

    pid_t fork();

    当一个进程调用了fork 以后,系统会创建一个子进程.这个子进程和父进程不同的地方只有他的进程ID 和父进程ID,其他的都是一样.就象符进程克隆(clone)自己一样当然创建两个一模一样的进程是没有意义的为了区分父进程和子进程,我们必须跟踪fork 的返回值.fork 掉用失败的时候(内存不足或者是用户的最大进程数已到)fork 返回-1否则fork 的返回值有重要的作用.对于父进程fork 返回子进程的ID而对于fork 子进程返回0我们就是根据这个返回值来区分父子进程的父进程为什么要创建子进程呢?前面我们已经说过了Linux 是一个多用户操作系统,在同一时间会有许多的用户在争夺系统的资源.有时进程为了早一点完成任务就创建子进程来争夺资源一旦子进程被创建,父子进程一起从fork 处继续执行,相互竞争系统的资源.有时候我们希望子进程继续执行而父进程阻塞直到子进程完成任务这个时候我们可以调用wait waitpid 系统调用

    Fork函数被调用一次,但返回两次。两次返回的唯一区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程ID。子进程获得父进程数据空间、堆和栈的副本。注意,这是子进程所拥有的副本。父子进程并不共享这些存储空间部分。

四、通过实例加深对多进程的理解
[root@test bdkyr]# cat fork_test.c

/*

*  create by bdkyr

*date 2015-1-21

*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>

#define MAXLINE 4096   /* max line length */

int glob = 6;
char buf[]= "a write to stdout\n";

void err_sys(const char *fmt, ...);
static void err_doit(int, int, const char *, va_list);

int main(void){
int var;
pid_t pid;
var = 88;
if (write (STDOUT_FILENO, buf, sizeof(buf) -1) != sizeof(buf)-1)
err_sys("write error");
printf("before fork\n");
if((pid = fork()) < 0){
err_sys("fork error");
}else if(pid == 0){
glob++;
var++;
}else{
sleep(2);
}
printf("pid=%d, glob = %d, var = %d\n", getpid(),glob, var);
exit(0);
}

void err_sys(const char *fmt, ...){
va_list ap;
va_start(ap, fmt);
err_doit(1, errno, fmt, ap);
va_end(ap);
exit(1);
}

static void err_doit(int errnoflag, int error, const char *fmt, va_list ap){
vsnprintf(buf, MAXLINE, fmt, ap);
if(errnoflag)
snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s", strerror(error));
strcat(buf, "\n");
fflush(stdout);
fputs(buf, stderr);
fflush(NULL);
}

[root@test bdkyr]# gcc fork_test.c -o fork_test
[root@test bdkyr]# ./fork_test                 
a write to stdout
before fork
pid=5209, glob = 7, var = 89
pid=5208, glob = 6, var = 88

五、总结
       说到底,多进程我们可以简单理解为,一个进程表示的,就是一个可执行程序的一次执行过程中的一个状态。操作系统对进程的管理,典型的情况,是通过进程表完成的。进程表中的每一个 表项,记录的是当前操作系统中一个进程的情况。对于单 CPU的情况而言,每一特定时刻只有一个进程占用 CPU,但是系统中可能同时存在多个活动的(等待执行或继续执行的)进程。fork()用于从已存进程中建立一个新进程,新进程为子进程,老进程为父进程.可以通过检查"fork()"地返回值知道哪个是子进程哪个是父进程。父进程得到的返回值是子进程的进程号,而子进程则返回0。
       您有收获吗?

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。