Linux 进程与信号

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()函数负责把一个流重定向到另外一个流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值