Linux 进程与信号

来源:互联网 发布:高级java工程师 工信部 编辑:程序博客网 时间:2024/06/05 06:39

Linux和Unix一样,有一个虚拟内存系统,能够把程序代码和数据以内存页面的形式放到硬盘的一个区域中,所以

Linux可以管理的进程比物理内存所能容纳的要多得多。

进程表

查看进程

ps -ef

TTY 一列显示了进程是从那个终端启动的。TIME一列是进程到目前为止所占用的CPU时间。

CMD一列显示启动进程使用的命令。STAT一列用来表明进程的当前代码。

STAT代码解释:

   睡眠,通常是等待某事件发生,如信号或有输入可用

   运行,严格来说是可运行,即在运行队列当中,处于正在执行或即将执行状态

   不可中断睡眠(等待)。通常是在等待输入输出完成

   停止。

   僵尸进程

   低优先级任务

   分页(不适用于2.6开始的版本)

   进程会话期首进程

   进程属于前台进程组

   多线程进程

   高优先级进程

启动新进程

#include<stdlib.h>

int system(const char *string);

system函数的作用是,运行以字符串参数的形式传递给它的命令并等待该命令的完成。命令的执行情况就如同在

shell中执行下列命令

$ sh -c string

1.替换进程映像

#include<unistd.h>int execl(const char *path, const char *arg0 , ... , (char *)0);int execlp(const char *file , const char *arg0, ... , (char *)0);int execle(const char *path , const char *arg0 , ... , (char *)0 , char *const envp[] );int execv(const char *path, const char *arg0 , ... , (char *)0);int execvp(const char *file , const char *arg0, ... , (char *)0);int execve(const char *path , const char *arg0 , ... , (char *)0 , char *const envp[] );

这些函数可以分为两类,execl,execlp和execle的参数个数是可变的,参数以一个空指针结构结束。

以字母P结尾的函数通过搜索path环境变量来查找程序的可执行文件的路径。

2.复制进程映像

#include<sys/types.h>#include<unistd.h>pid_t fork(void);
子进程中的fork调用返回的是0,父子进程可以通过这一点来判断究竟谁是父进程,谁是子进程。

经过fork调用后,父进程返回一个新的进程PID,子进程返回0。

#include <sys/types.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main(){    pid_t pid;    char *message;    int n;    printf("fork program starting\n");    pid = fork();    switch(pid)     {    case -1:        perror("fork failed");        exit(1);    case 0:        message = "This is the child";        n = 5;        break;    default:        message = "This is the parent";        n = 3;        break;    }    for(; n > 0; n--) {        puts(message);        sleep(1);    }    exit(0);}
等待一个进程

#include<sys/types.h>#include<sys/wait.h>pid_t wait(int *stat_loc);
wait系统调用将父进程知道它的子进程结束为止。这个调用返回子进程的PID,它通常是已经结束运行的子进程的PID。

我们可以用sys/wait.h文件定义的宏来解释状态信息。如表11-2所示

                                   宏                                                   说明

WIFEXITED(stat_val)                                          如果子进程正常结束,它就取一个非零值。

WEXITSTATUC(stat_val)                                   如果WIFEXITED非零,它就返回子进程的退出码。

WIFSIGNALED(stat_val)                                    如果子进程因为一个未捕获的信号而终止,它就取一个非零值。

WTERMSIG(stat_val)                                         如果WIFSIGNALED非零,它返回一个信号代码。

WIFSTOPPED(stat_val)                                    如果子进程意外终止,它就取一个非零值。

WSTOPSIG(stat_val)                                         如果WIFSTOPPED非零,它返回一个信号代码

#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main(){    pid_t pid;    char *message;    int n;    int exit_code;    printf("fork program starting\n");    pid = fork();    switch(pid)     {    case -1:        exit(1);    case 0:        message = "This is the child";        n = 5;        exit_code = 37;        break;    default:        message = "This is the parent";        n = 3;        exit_code = 0;        break;    }    for(; n > 0; n--) {        puts(message);        sleep(1);    }/*  This section of the program waits for the child process to finish.  */    if(pid) {        int stat_val;        pid_t child_pid;        child_pid = wait(&stat_val);        printf("Child has finished: PID = %d\n", child_pid);        if(WIFEXITED(stat_val))            printf("Child exited with code %d\n", WEXITSTATUS(stat_val));        else            printf("Child terminated abnormally\n");    }    exit (exit_code);}
僵尸进程

用fork来创建进程确实很有用,但你必须清楚子进程的运行情况。子进程终止时,它与父进程之间的关联还会保持。

直到父进程也正常终止或父进程调用wait才告结束。因此,进程表中代表子进程的表项不会立刻释放。虽然子进程

已经不再运行,但它依然存在系统中,因为它的退出码还需要保存起来,以备父进程今后的wait调用使用。这时它

成为一个死进程或僵尸进程。

还有一个系统调用可以用来等待子进程的结束,它是waitpid函数。你可以用它来等待某个特定的进程结束。

#include<sys/types.h>

#include<sys/wait.h>

pid_t waitpid(pid_t pid, int *stat_loc , int options);


输入输出重定向

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


/*  This code, useupper.c, accepts a file name as an argument    and will respond with an error if called incorrectly.  */#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main(int argc, char *argv[]){    char *filename;    if(argc != 2) {        fprintf(stderr, "usage: useupper file\n");        exit(1);    }    filename = argv[1];/*  That done, we reopen the standard input, again checking for any errors as we do so,    and then use execl to call upper.  */    if(!freopen(filename, "r", stdin)) {        fprintf(stderr, "could not redirect stdin to file %s\n", filename);        exit(2);    }    execl("./upper", "upper", 0);/*  Don't forget that execl replaces the current process;    provided there is no error, the remaining lines are not executed.  */    perror("could not exec ./upper");    exit(3);}

freopen()函数负责把一个流重定向到另外一个流。

原创粉丝点击