Chinaunix首页 | 论坛 | 博客
  • 博客访问: 366322
  • 博文数量: 36
  • 博客积分: 2071
  • 博客等级: 大尉
  • 技术积分: 797
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-20 12:08
文章分类
文章存档

2011年(2)

2010年(34)

我的朋友

分类: LINUX

2010-11-21 19:39:33

进程
    进程与程序的关系,首先说明一下什么是程序
  程序是存放在磁盘上,处于某个目录下的一个可执行文件。程序是静态的,它是一些保存在磁盘上的指令的所有集合。然而程序的实例化被称为进程,进程是linux事物的基本单元。所有进程都拥有自己的独立的处理环境和系统资源。进程的环境由当前系统状态及其父进程信息决定和组成。在Linux环境下第一个进程init由内核产生,以后的进程都是通过fork函数产生的。进程是一个动态的概念,它是程序执行的过程,包括动态创建,调度和消亡的整个过程。
    进程的属性
基本属性包括进程号(PID)、父进程号(PPID)、进程组号(PGID)。PID唯一的标识了一个进程,PID是无法在用户层修改的。比如说Linux系统下,系统第一个由内核产生的进程init进程号PID的值是整数1,由fork函数产生的进程的PID依次增加。我们可以通过“ps aux”命令查看系统当前所有进程的基本属性。例如
[root@loclhost ~]#ps aux
USER PID %CPU %MEN VSZ RSS TTY  STAT START
root   1   0.0 0.3  1748 572 ?   S    04:12
root   2   0.0 0.0  0     0  ?   SN   04:12
TIME COMMAND
0:02 init [3]
0:02 [ksofttirgd/0]
我们可以通过getpid()函数获得当前进程的PID。父进程号,任何进程除了init外都是由另一个进程创建的,这个所说的另一进程就是该进程的父进程,被创建的进程也就名正言顺的叫做子进程了。父进程号也是无法在用户层修改的,父进程的进程号在子进程中叫做PPID,用户可以在子进程中通过getppid()函数获得子进程的父进程号。进程组号,在Linux系统下,每个用户都拥有用户号(UID)和用户组号(GUID);和用户管理一样进程也拥有自己的进程号(PID)和进程组号(PGID)。进程组是一个进程和多个进程的集合。他们与同一作业相关,可以接受来自同一终端的信号,每个进程组都有唯一的组号,这个我们是可以通过用户层修改的。哈哈哈哈,我们可以通过getpgid()函数获得进程组号。
用户属性真实的用户号(RUID)、真实用户组号(RGID)、有效用户号(EUID)、有效用户组号(EGID)
 
进程的状态
 
进程的整个生命周期可划分为三种状态:
1、执行态:该进程正在占用cpu运行
2、就绪态:进程已经具备执行的一切条件,正在等待分配cpu的处理时间。
3、等待态:进程正在等待某事件的发生
 
进程控制
fork函数:创建一个新的进程
如下例:
#include
 
pid_t pid;
pid = fork();
 
简单的说明一下fork函数:
返回值:在子进程中返回0,父进程中返回子进程ID
 
    一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。
  子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间,它们之间共享的存储空间只有代码段。
我们可以从这个代码实例中了解到什么:

/* ************************************************************************
 * Filename: fork-1.c
 * Description:
 * Version: 1.0
 * Created: 2010年11月21日 19时18分26秒
 * Revision: none
 * Compiler: gcc
 * Author: YOUR NAME (wangbaoqi),
 * Company:
 * ************************************************************************/



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    int num = 10;
    pid_t pid;
    pid = fork();
    
//pid=fork();

    if(pid < 0)
        perror("fork");
    if(0 == pid)
    {
        num = num+2;
        printf("This is son procsse is %d,num = %d\n",getpid(),num);
    }
    else
    {
        num++;
        printf("this is father process is %d,num=%d\n",pid,num);
        printf("my id is %d\n",getppid());
    }
    return 0;
}


/* ************************************************************************
 * Filename: fork-2.c
 * Description:
 * Version: 1.0
 * Created: 2010年11月21日 20时08分16秒
 * Revision: none
 * Compiler: gcc
 * Author: YOUR NAME (wangbaoqi),
 * Company:
 * ************************************************************************/



#include <stdio.h>

#include <stdlib.h>
#include <unistd.h>
int glob = 6;
char buf[] = "a write to stdout\n";
int main(int argc, char *argv[])
{
    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");
    if((pid = fork())<0)
    {
        printf("fork error\n");
    }
    else if(pid == 0)
    {
        glob++;
        var++;
    }
    else
    {
        sleep(2);
    }
    printf("pid=%d,glob=%d,var=%d\n",getpid(),glob,var);
    return 0;
}
vfork()函数:创建一个新进程
#include 
pid_t pid;
pid = vfork ()
简单的说明一下vfork函数:
返回值:在子进程中返回0,父进程中返回子进程ID
vfork()会产生一个新的子进程,其子进程会复制父进程
的数据与堆栈空间,并继承父进程的用户代码,组代码,环
境变量、已打开的文件代码、工作目录和资源限制等。
Linux 使用copy-on-write(COW)技术,只有当其中一
进程试图修改欲复制的空间时才会做真正的复制动作,由于
这些继承的信息是复制而来,并非指相同的内存空间,因此
子进程对这些变量的修改和父进程并不会同步。此外,子进
程不会继承父进程的文件锁定和未处理的信号。注意,
Linux不保证子进程会比父进程先执行或晚执行,因此编写
程序时要留意死锁或竞争条件的发生。 
 

 




/* ************************************************************************
 * Filename: vfork-1.c
 * Description:
 * Version: 1.0
 * Created: 2010年11月21日 20时15分15秒
 * Revision: none
 * Compiler: gcc
 * Author: YOUR NAME (wangbaoqi),
 * Company:
 * ************************************************************************/



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    pid_t pid;
    pid = vfork();
    if(pid<0)
        perror("vfork");
    if(pid == 0)
    {
        sleep(2);
        printf("This is a child process!%d\n",getpid());
        exit(0);
    }
    else
    {
        printf("This is father process!%d\n",pid);
    }
    return 0;
}



/* ************************************************************************
 * Filename: vfork-2.c
 * Description:
 * Version: 1.0
 * Created: 2010年11月21日 20时28分00秒
 * Revision: none
 * Compiler: gcc
 * Author: YOUR NAME (wangbaoqi),
 * Company:
 * ************************************************************************/



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    pid_t pid;
    int num = 100;
    pid = vfork();
    if(pid<0)
        perror("vfork");
    if(0 == pid)
    {
        sleep(2);
        num++;
        printf("This is child process: pid=%d,num=%d\n",getpid(),num);
        num = num+13;
        exit(0);
    }
    else
    {
        printf("This is father process: pid=%d,num=%d\n",pid,num);
    }

    return 0;
}



阅读(1720) | 评论(1) | 转发(1) |
给主人留下些什么吧!~~

chinaunix网友2010-11-23 13:45:17

非常好 经典 简单 易懂 知识点全