进程

来源:互联网 发布:mysql 存储过程 参数 编辑:程序博客网 时间:2024/04/30 19:32

一.进程

1.什么是进程

    定义:一个其中运行着一个或者多个线程的地址空间和这些线程所需要的系统资源

2.进程的结构

    如果有两个用户neil和rick,他们同时运行grep程序在不同的文件中查找不同的字符串。

    如果在搜索结束之前运行ps -ef 命令,则出现以下内容。

    $ps -ef

     UID     PID   PPID   C   STIME   TTY   TIME        CMD

     rick     101    96       0    18:24     tty2   00:00:00   grep tr n.txt  

     neil     102    92       0    18:24     tty4  00:00:00   grep hr u.txt 

结论:

  • 每一个进程都会被分配唯一的一个数字编号,叫进程标识符或者PID。他通常取值为2到32768的正整数。1为特殊进程init
  • 将要被grep执行的程序代码被保存在一个磁盘文件中,正常情况下,linux进程不能对用来存放程序代码的内存区域进行写操作,即程序代码是以只读方式加载到内存中去的。可以被多个进程安全的共享。
  • 系统函数库也可以被共享。例如,不管有多少个运行的程序要调用printf函数,内存中只要有它的一个副本即可。
  • 进程有自己的栈空间,用于保存局部变量和控制函数的调用和返回。
  • 进程有自己的环境空间用于保存自己的环境变量。
  • 进程还必须保存自己的程序计数器,用于保存执行的位置。
2
        2.1进程表
             一个数据结构,把当前加载在内存中的所有进程有关的         信息都保存在一个表中
        2.1查看进程
      $ps -ef
      默认情况下,p程序只显示与终端,主控台、串行口或          者伪终端保持连接的进程的信息。其他进程运行时不需要与        终端和用户进行通信。
             ps -a      查看所有的进程
             pa -f       显示进程完整的信息
2.3系统进程
    $ps -ax
   PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:01 /sbin/init
    2 ?        S      0:00 [kthreadd]
    3 ?        S      0:00 [migration/0]
    4 ?        S      0:00 [ksoftirqd/0]
    5 ?        S      0:00 [migration/0]
    6 ?        S      0:00 [watchdog/0]
    7 ?        S      0:00 [events/0]
    8 ?        S      0:00 [cgroup]
    9 ?        S      0:00 [khelper]
   10 ?        S      0:00 [netns]
   11 ?        S      0:00 [async/mgr]
   12 ?        S      0:00 [pm]
   13 ?        S      0:00 [sync_supers]
   14 ?        S      0:00 [bdi-default]
   15 ?        S      0:00 [kintegrityd/0]
   16 ?        S      0:00 [kblockd/0]
   17 ?        S      0:00 [kacpid]
   18 ?        S      0:00 [kacpi_notify]
   19 ?        S      0:00 [kacpi_hotplug]
   20 ?        S      0:00 [ata/0]
   21 ?        S      0:00 [ata_aux]
   22 ?        S      0:00 [ksuspend_usbd]
   23 ?        S      0:00 [khubd]
   24 ?        S      0:00 [kseriod]
   25 ?        S      0:00 [md/0]
   26 ?        S      0:00 [md_misc/0]
   27 ?        S      0:00 [khungtaskd]
   28 ?        S      0:00 [kswapd0]
   29 ?        SN     0:00 [ksmd]
   30 ?        S      0:00 [aio/0]
   31 ?        S      0:00 [crypto/0]
   36 ?        S      0:00 [kthrotld/0]
   37 ?        S      0:00 [pciehpd]
   39 ?        S      0:00 [kpsmoused]
   40 ?        S      0:00 [usbhid_resumer]
   70 ?        S      0:00 [kstriped]
  327 ?        S      0:00 [mpt_poll_0]
  328 ?        S      0:00 [mpt/0]
  329 ?        S      0:00 [scsi_eh_0]
  335 ?        S      0:00 [scsi_eh_1]
  336 ?        S      0:00 [scsi_eh_2]
  346 ?        S      0:00 [scsi_eh_3]
  347 ?        S      0:01 [scsi_eh_4]
  348 ?        S      0:00 [scsi_eh_5]
  349 ?        S      0:00 [scsi_eh_6]
  350 ?        S      0:00 [scsi_eh_7]
  351 ?        S      0:00 [scsi_eh_8]
  352 ?        S      0:00 [scsi_eh_9]
  353 ?        S      0:00 [scsi_eh_10]
  354 ?        S      0:00 [scsi_eh_11]
  355 ?        S      0:00 [scsi_eh_12]
  356 ?        S      0:00 [scsi_eh_13]
  357 ?        S      0:00 [scsi_eh_14]
  358 ?        S      0:00 [scsi_eh_15]
  359 ?        S      0:00 [scsi_eh_16]
  360 ?        S      0:00 [scsi_eh_17]
  361 ?        S      0:00 [scsi_eh_18]
  362 ?        S      0:00 [scsi_eh_19]
  363 ?        S      0:00 [scsi_eh_20]
  364 ?        S      0:00 [scsi_eh_21]
  365 ?        S      0:00 [scsi_eh_22]
  366 ?        S      0:00 [scsi_eh_23]
  367 ?        S      0:00 [scsi_eh_24]
  368 ?        S      0:00 [scsi_eh_25]
  369 ?        S      0:00 [scsi_eh_26]
  370 ?        S      0:00 [scsi_eh_27]
  371 ?        S      0:00 [scsi_eh_28]
  372 ?        S      0:00 [scsi_eh_29]
  373 ?        S      0:00 [scsi_eh_30]
  374 ?        S      0:00 [scsi_eh_31]
  375 ?        S      0:00 [scsi_eh_32]
  492 ?        S      0:01 [jbd2/sda2-8]
  493 ?        S      0:00 [ext4-dio-unwrit]
  515 ?        S      0:00 [flush-8:0]
  580 ?        S<s    0:00 /sbin/udevd -d
  778 ?        S      0:00 [vmmemctl]
 1071 ?        S      0:00 [bluetooth]
 1144 ?        S<     0:00 /sbin/udevd -d
 1145 ?        S<     0:00 /sbin/udevd -d
 1188 ?        S      0:00 [jbd2/sda1-8]
 1189 ?        S      0:00 [ext4-dio-unwrit]
 1240 ?        S      0:00 [kauditd]
 1488 ?        Ssl    0:00 /usr/sbin/vmware-vmblock-fuse -o subtype=vmware-vmblo
 1521 ?        Sl     0:06 /usr/sbin/vmtoolsd
 1726 ?        Sl     0:00 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
 1768 ?        Ss     0:00 rpcbind
 1783 ?        Ssl    0:00 dbus-daemon --system
 1794 ?        Ss     0:00 NetworkManager --pid-file=/var/run/NetworkManager/Net
 1800 ?        S      0:00 /usr/sbin/modem-manager
 1806 ?        S      0:00 avahi-daemon: running [linux.local]
 1807 ?        Ss     0:00 avahi-daemon: chroot helper
 1810 ?        Ss     0:00 /usr/sbin/wpa_supplicant -c /etc/wpa_supplicant/wpa_s
 1827 ?        Ss     0:00 rpc.statd
 1861 ?        S      0:00 [rpciod/0]
 1865 ?        Ss     0:00 rpc.idmapd
 1875 ?        Ss     0:00 cupsd -C /etc/cups/cupsd.conf
 1900 ?        Ss     0:00 /usr/sbin/acpid
 1909 ?        Ss     0:00 hald
 1910 ?        S      0:00 hald-runner
 1940 ?        S      0:00 /usr/libexec/hald-addon-rfkill-killswitch
 1951 ?        S      0:00 hald-addon-input: Listening on /dev/input/event2 /dev
 1957 ?        S      0:00 hald-addon-acpi: listening on acpid socket /var/run/a
 1976 ?        Ssl    0:00 automount --pid-file /var/run/autofs.pid
 1994 ?        S<s    0:00 /usr/sbin/bluetoothd --udev
 2005 ?        Ss     0:00 /usr/sbin/sshd
 2098 ?        Ss     0:00 tpvmlpd2
 2118 ?        S<     0:00 [krfcommd]
 2255 ?        Ss     0:00 /usr/libexec/postfix/master
 2262 ?        S      0:00 pickup -l -t fifo -u
 2263 ?        S      0:00 qmgr -l -t fifo -u
 2279 ?        Ss     0:00 /usr/sbin/abrtd
 2287 ?        Ss     0:00 abrt-dump-oops -d /var/spool/abrt -rwx /var/log/messa
 2295 ?        Ss     0:00 crond
 2311 ?        Ss     0:00 /usr/sbin/atd
 2326 ?        Ss     0:00 /usr/bin/rhsmcertd 240 1440
 2342 ?        Ss     0:00 /usr/sbin/certmonger -S -p /var/run/certmonger.pid
 2349 ?        Ss     0:00 /usr/sbin/gdm-binary -nodaemon
 2354 tty2     Ss+    0:00 /sbin/mingetty /dev/tty2
 2356 tty3     Ss+    0:00 /sbin/mingetty /dev/tty3
 2358 tty4     Ss+    0:00 /sbin/mingetty /dev/tty4
 2360 tty5     Ss+    0:00 /sbin/mingetty /dev/tty5
 2364 tty6     Ss+    0:00 /sbin/mingetty /dev/tty6
 2377 ?        S      0:00 /usr/libexec/gdm-simple-slave --display-id /org/gnome
 2379 tty1     Ss+    0:09 /usr/bin/Xorg :0 -nr -verbose -audit 4 -auth /var/run
 2395 ?        Sl     0:00 /usr/sbin/console-kit-daemon --no-daemon
 2465 ?        S      0:00 /usr/bin/dbus-launch --exit-with-session
 2471 ?        S      0:00 /usr/libexec/devkit-power-daemon
 2515 ?        S      0:00 /usr/libexec/polkit-1/polkitd
 2522 ?        SNl    0:00 /usr/libexec/rtkit-daemon
 2528 ?        S      0:00 pam: gdm-password
 2611 ?        Sl     0:00 /usr/bin/gnome-keyring-daemon --daemonize --login
 2620 ?        Ssl    0:00 gnome-session
 2628 ?        S      0:00 dbus-launch --sh-syntax --exit-with-session
 2629 ?        Ssl    0:00 /bin/dbus-daemon --fork --print-pid 5 --print-address
 2657 ?        S      0:00 /usr/libexec/gconfd-2
 2666 ?        Ssl    0:00 /usr/libexec/gnome-settings-daemon
 2673 ?        Ss     0:00 seahorse-daemon
 2676 ?        S      0:00 /usr/libexec/gvfsd
 2684 ?        Sl     0:00 metacity
 2693 ?        S<sl   0:02 /usr/bin/pulseaudio --start --log-target=syslog
 2694 ?        S      0:00 gnome-panel
 2701 ?        S      0:00 /usr/libexec/pulse/gconf-helper
 2702 ?        S      0:08 nautilus
 2704 ?        Ssl    0:00 /usr/libexec/bonobo-activation-server --ac-activate -
 2712 ?        S      0:00 /usr/libexec/wnck-applet --oaf-activate-iid=OAFIID:GN
 2713 ?        S      0:00 /usr/libexec/trashapplet --oaf-activate-iid=OAFIID:GN
 2715 ?        S      0:00 /usr/libexec/gvfs-gdu-volume-monitor
 2717 ?        S      0:00 /usr/libexec/udisks-daemon
 2719 ?        S      0:00 /usr/libexec/gvfsd-trash --spawner :1.7 /org/gtk/gvfs
 2720 ?        S      0:01 udisks-daemon: polling /dev/sr0
 2723 ?        S      0:00 /usr/libexec/gdu-notification-daemon
 2724 ?        Sl     0:13 /usr/lib/vmware-tools/sbin32/vmtoolsd -n vmusr --bloc
 2725 ?        S      0:00 gpk-update-icon
 2729 ?        S      0:00 gnome-volume-control-applet
 2730 ?        S      0:00 nm-applet --sm-disable
 2731 ?        S      0:00 gnome-power-manager
 2735 ?        S      0:00 bluetooth-applet
 2737 ?        S      0:00 rhsm-icon
 2745 ?        S      0:00 abrt-applet
 2749 ?        S      0:00 /usr/libexec/im-settings-daemon
 2750 ?        S      0:00 /usr/sbin/restorecond -u
 2752 ?        S      0:00 python /usr/share/system-config-printer/applet.py
 2758 ?        S      0:00 /usr/libexec/polkit-gnome-authentication-agent-1
 2764 ?        S      0:00 /usr/libexec/gvfs-gphoto2-volume-monitor
 2772 ?        Sl     0:00 /usr/libexec/gvfs-afc-volume-monitor
 2948 ?        S      0:00 /usr/libexec/notification-daemon
 2955 ?        Sl     0:00 /usr/bin/ibus-daemon -r --xim
 2958 ?        S      0:00 /usr/libexec/gconf-im-settings-daemon
 2959 ?        Ss     0:03 gnome-screensaver
 2968 ?        S      0:00 /usr/bin/gnote --panel-applet --oaf-activate-iid=OAFI
 2969 ?        S      0:00 /usr/libexec/clock-applet --oaf-activate-iid=OAFIID:G
 2970 ?        S      0:00 /usr/libexec/gdm-user-switch-applet --oaf-activate-ii
 2971 ?        S      0:00 /usr/libexec/notification-area-applet --oaf-activate-
 2977 ?        S      0:00 /usr/libexec/ibus-gconf
 2979 ?        S      0:00 python /usr/share/ibus/ui/gtk/main.py
 2981 ?        S      0:00 /usr/libexec/ibus-x11 --kill-daemon
 2982 ?        S      0:00 /usr/libexec/ibus-engine-pinyin --ibus
 3024 ?        S      0:00 /usr/libexec/gvfsd-burn --spawner :1.7 /org/gtk/gvfs/
 3027 ?        S      0:00 /usr/libexec/gvfsd-metadata
 3063 ?        Sl     0:02 gnome-terminal
 3064 ?        S      0:00 gnome-pty-helper
 3065 pts/0    Ss     0:00 bash
 3228 ?        Ss     0:00 /usr/sbin/anacron -s
 3617 ?        S      0:00 /usr/libexec/fprintd
 3625 pts/0    R+     0:00 ps ax

 
STAT表明进程的当前状态STAT代码说明S睡眠R运行D不可中断睡眠(等待)等输入或者等待输出T停止Z 死进程或者僵尸进程N低优先级任务W分页s进程是会话期首进程+进程属于前台进程组l进程是多线程的<高优先级任务
      其中 1 ?        Ss     0:01 /sbin/init
      一般而言每一个进程都是由其他父进程启动的。lnit是系统     运行的第一个进程,也就是祖先进程

2.4进程调度

3625 pts/0    R+     0:00 ps ax
  • R+表示程序已经准备好运行,并不意味着它正在运行。所以只能表示这是一个前台任务。
  • 时间片概念
  • 表现良好的程序称为nice程序。在多任务系统中,多个进程可能竞争同一个资源。在这种情况下,执行短期的突发性工作并暂停运行等待输入的程序,要比持续占用处理器来进行计算或者不断轮询系统来查看是否有心得输入到达的程序要更好。
  • 系统会根据nice值来决定它的优先级
  • nice命令设置进程的优先级,renice命令调整它的值。nice命令将他的nice值增加10,从而降低它的nice值。(NI为nice 值)
$ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S   500  3065  3063  0  80   0 -  1310 -      pts/0    00:00:00 bash
0 R   500  4167  3065  5  80   0 -  1615 -      pts/0    00:00:00 oclock
0 R   500  4168  3065  5  80   0 -  1215 -      pts/0    00:00:00 ps
$niceoclock &
$reniceoclock 4168
$ps -l
$ps x
  •         其中STAT中N字符表明这个进程的nice已经被修改了
PID    TTY      STAT   TIME COMMAND
1362  PTS/1    SN      0:00  oclock
  • 如果父进程已经不存在,则父进程为1(init)
3.启动新进程
在程序的内部启动另外一个新进程。
 #include <stdlib.h>


     
          int system(const char *command);

  • system函数的作用是:运行以字符串形式创递给它的命令等待该命令的完成。命令的执行情况就如同在shell中执行如下命令。
$sh -c string
  • sysrem的返回值:如果无法启动shell执行这个命令,system函数返回错误代码127;如果是其他错误,则返回-1;否则,system函数将返回该命令的退出码。
  • 用system 编写一个程序,让它替我们运行ps程序。
#include<stdlib.h>
#include<stdio.h>


int main()
{
    printf("Running ps with system\n");
    system("ps ax");
    printf("Done.\n");
    exit(0);
}

$./system1

Running ps with system
  PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:02 /sbin/init
    2 ?        S      0:00 [kthreadd]

........

    3261 ?        S      0:00 /usr/sbin/packagekitd

    3274 pts/0    S+     0:00 ./system1

    3275 pts/0    R+     0:00 ps ax

Done.


修改程序为system("ps ax &")


$./system1

Running ps with system
Done.
[hui@localhost 517]$   PID TTY      STAT   TIME COMMAND
    1 ?        Ss    0:02 /sbin/init
    2 ?        S      0:00 [kthreadd]

......

 3137 ?        S      0:00 /usr/libexec/notification-daemon
 3329 pts/0    R      0:00 ps ax

实验分析:"ps ax "为参数时,system函数在执行完ps命令后返回。必须由system启动的进程结束后才能继续,不能执行其他任务。

  "pa ax &"为参数时,ps程序一启动它就返回了。

  • system对shell的依赖性很大,效率不高。
3.1替换进程映像
  •   exec系列函数由一组相关的函数组成。
  • exec函数可以把当前进程替换为一个新进程,新进程由path函数和file参数制定。
  • exec函数比system函数更有效,在心得程序启动后,就不用运行原来的程序了。   
  • #include <unistd.h>


           extern char **environ;


           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 *filename, char *const argv[],

                  char *const envp[]);


  1. 函数分为两大类,execlexeclpexecle是可变参的,参数以一个空指针结束。 execv execvp的第二个参数是字符串数组。新程序启动时会把argv数组中给定的参数传递给main函数。
  2. 这些函数通常都是由execve实现的,虽然没有必要这样做。
  3. 以字母p结尾的函数通过PATH环境变量来查找新程序可执行文件的路径。如果可执行文件的路径不在PATH定义的路径中,我们就需要在包括目录在内的绝对路径的文件名作为参数传递给函数。
  • 试验程序
#include<unistd.h>

#include<stdlib.h>

#include<stdio.h>



char *const ps_argv[] = {"ps","ax",0};

char *const ps_envp[] = {"PATH=/bin:/usr/bin","TERM=console",0};



int main()

{

    printf("Running pa with exec\n");

    //execl("/bin/ps","ps","ax",0);

    execlp("ps","ps","ax",0);

    //execle("/bin/ps","ps","ax",ps_envp);



    //execv("/bin/ps",ps_argv);

    //execvp("ps",ps_argv);

    //execve("/bin/ps",ps_argv,ps_envp);



    exit(0);

}

一般情况下,exec函数是不会反回的,除非发生了错误。出现错误时,exec函数返回-1,并且设置错误变量errno。

由exec启动的新程序继承了原来的程序的多样性,特别的,在原进程打开的文件描述符在新进程中任然保持打开,除非他们的"执行关闭标志(close on exec flag)被设置"(fcntl系统调用)。任何在原程序目标流都将在新程序中关闭。

3.2 复制进程映像

要想要一个进程同时执行多个函数,可以用线程或者从原程序中创建一个分离的进程,后者就像init一样,而不像exec调用那样用新的程序替换当前执行的线程。

fork创建一个新进程:这个系统调用复制当前进程,在进程表中创建一个新的表项,新表项中有许多属性都和当前进程一模一样,执行的代码也完全相同,但新进程有自己的数据空间、环境和文件描述符。

 #include <unistd.h>


  pid_t fork(void);

父进程返回子进程的PID,子进程返回0;

2.1等待一个进程

我们希望知道子进程在何时结束。可以在父进程中调用wait函数等待子进程的结束。

 #include <sys/wait.h>

pid_t wait(int *stat_loc);

wait系统代用将暂停父进程知道子进程结束为止,这个调用返回子进程的PID,stat_loc指向子进程的退出码。

2.2僵尸进程

子进程终止时,他与父进程之间的还会保持联系,直到父进程也正常终止或者父进程盗用wait才结束。

因此代表子进程的表项不会立刻释放,虽然子进程已经结束,但它仍然存在于系统中,,因为它的退出码还需要保存起来,以备以后的父进程wait调用使用。此时他将会成为一个僵(zombie)尸进程或者死(defunct)进程。

实例

父进程先结束:

#include<stdio.h>

#include<stdlib.h>

#include<sys/types.h>

#include<unistd.h>

#include<sys/wait.h>



int main()

{

    char *message;



    int n;

    int exit_code;



    printf("forring\n");

    pid_t pid = fork();

    switch(pid)

    {

        case -1:

            perror("fork failed");

            exit(1);

        case 0:

            message = "child";

            n = 5;

            exit_code = 100;

            break;

        default:

            message = "father";

            n = 3;

            exit_code = 50;

            break;

    }



    while(n)

    {

        puts(message);

        --n;

    }



    if(pid != 0)

    {

        int stat_val;

        pid_t childpid = wait(&stat_val);



        printf("child( PID = %d ) finished\n",childpid);

        if(WIFEXITED(stat_val))

        {

            printf("child exited with code %d\n",WEXITSTATUS(stat_val));

        }

        else

        {

            printf("child terminated abnormally\n");

        }

    }

    exit(exit_code);

}


$ gcc -o fork1 fork1.c

$ ./fork1 

forring
father
child
father
child
father
child
child
child
child( PID = 3342 ) finished
child exited with code 100


子进程先结束:


#include<stdio.h>

#include<stdlib.h>

#include<sys/types.h>

#include<unistd.h>

#include<sys/wait.h>



int main()

{

    char *message;



    int n;

    int exit_code;



    printf("forring\n");

    pid_t pid = fork();

    switch(pid)

    {

        case -1:

            perror("fork failed");

            exit(1);

        case 0:

            message = "child";

            n = 5;

            exit_code = 100;

            break;

        default:

            message = "father";

            n = 3;

            exit_code = 50;

            break;

    }



    while(n)

    {

        puts(message);

        --n;

    }



    if(pid != 0)

    {

        int stat_val;

        pid_t childpid = wait(&stat_val);



        printf("child( PID = %d ) finished\n",childpid);

        if(WIFEXITED(stat_val))

        {

            printf("child exited with code %d\n",WEXITSTATUS(stat_val));

        }

        else

        {

            printf("child terminated abnormally\n");

        }

    }

    exit(exit_code);

}


 $./fork2

forring
father
child
father
child
father
child
father
father
child( PID = 3473 ) finished

child exited with code 100

$ ps -al(在子进程结束以后父进程未结束时ps)

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S   500  3472  2982  0  80   0 -   462 -      pts/0    00:00:00 fork2
1 Z   500  3473  3472  0  80   0 -     0 ?      pts/0    00:00:00 fork <defunct>
0 R   500  3475  3256  0  80   0 -  1215 -      pts/1    00:00:00 ps

  • 如果此时父进程异常终止,子进程将由init接管,子进程将是一个不在运行的僵尸进程,僵尸进程将一直保留在进程表中直到被init发现并释放。
  • 进程表越大,init发现就越慢。在init发现他们之前,一直占用系统资源


 #include <sys/types.h>
       #include <sys/wait>
       pid_t waitpid(pid_t pid, int *status, int options); 

3.3输入输出重定向

实验upper.c

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
    int ch;
    while((ch = getchar()) != EOF)
    {
        putchar(toupper(ch));
    }
    exit(0);
}


$ ./upper 
hello world
HELLO WORLD


$ ./upper < upper.c
#INCLUDE<STDIO.H>
#INCLUDE<STDLIB.H>
#INCLUDE<CTYPE.H>
INT MAIN()
{
    INT CH;
    WHILE((CH = GETCHAR()) != EOF)
    {
        PUTCHAR(TOUPPER(CH));
    }
    EXIT(0);
}











   



原创粉丝点击