04 读书笔记:第1章 UNIX基础知识 (3)

1 进程  

      程序是存放在磁盘上、处于某个目录中的可执行文件。程序的执行实例称为进程。UNIX系统确保每一个进程都有唯一的数字标识符,称为进程ID。进程ID总是一非负数。

        《UNIX环境高级编程》P8: 程序清单1-4  打印进程ID(有改动)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    printf("hello world from process ID %d\n", getpid());    // getpid()获取进程ID
    exit(0);
}

2 进程控制

        用户进程控制的函数主要有三个:fork、exec和waitpid。(exec函数有六种变体,但经常把它们统称为exec函数)

        《UNIX环境高级编程》P9: 程序清单1-5 从标准输入读命令并执行(有改动)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

#define MAXLINE 4096

int main()
{
    char    buf[MAXLINE];
    pid_t   pid;
    int     status;

    printf("%% ");
    while (fgets(buf, MAXLINE, stdin) != NULL) {    // 从标准输入一次读取一行,当键入文件结束符(Ctrl+D),fgets返回null指针
        if (buf[strlen(buf) - 1] == '\n')           // fgets返回的每一行都以换行符终止,随后一个null字节,需要去除换行符
            buf[strlen(buf) - 1] = 0;               // 用一个null字节替换换行符

        if ((pid = fork()) < 0) {                   // fork创建一个新进程(子进程)。新进程是调用进程的复制品
            fprintf(stderr, "fork error");
        } else if (pid == 0) {                      // fork对父进程返回子进程ID(非负),对子进程返回0。(fork调用一次,返回两次)
            /* 子进程 */
            execlp(buf, buf, (char *) 0);           // 执行从标准输入读入的命令,新的程序文件替换子进程原先的执行文件
            fprintf(stderr, "couldn't execute: %s\n", buf);
            exit(127);
        }
        /* 父进程部分,子进程不会执行 */
        if (( pid = waitpid(pid, &status, 0)) < 0)  // 父进程等待子进程终止,pid为子进程ID,status返回子进程的状态
            fprintf(stderr, "waitpid error");
        printf("%% ");
    }   
    printf("\n");
    exit(0);
}

        执行:

$ ./05
% dir
01  01.c  02  02.c  03	03.c  04  04.c	05  05.c  Makefile
%

3 线程

        多个控制线程能充分利用多处理器的并行性。

        在一个进程内的所有线程共享同一地址空间、文件描述符、栈以及与进程相关的属性。因为它们能访问同一存储区,所以各个线程在访问共享数据时需要采取同步措施以避免不一致性 。

        与进程相同,线程也用ID标识。但线程ID只在它所属进程内起作用。当在同一进程中对多个线程进行操作时,用线程ID引用相应的线程。  

PS:

        我对fork函数的理解:

        1. 执行fork创建一个新进程,新进程是调用进程的复制品。执行到的位置都一样。

         04 读书笔记:第1章 UNIX基础知识 (3)

        2. fork向父进程返回子进程ID,对子进程返回0,所以父、子进程会执行不同部分。(父、子进程包含相同的代码)

        子进程执行部分:

        } else if (pid == 0) {                      // fork对父进程返回子进程ID(非负),对子进程返回0。(fork调用一次,返回两次)
            /* 子进程 */
            execlp(buf, buf, (char *) 0);           // 执行从标准输入读入的命令,新的程序文件替换子进程原先的执行文件
            fprintf(stderr, "couldn't execute: %s\n", buf);
            exit(127);
        }

        父进程执行部分:

        /* 父进程部分,子进程不会执行 */
        if (( pid = waitpid(pid, &status, 0)) < 0)  // 父进程等待子进程终止,pid为子进程ID,status返回子进程的状态
            fprintf(stderr, "waitpid error");
        printf("%% ");

        3. 当子进程执行到 execlp函数时,新的程序文件会替换原来的程序文件。因此子进程可以执行不同的程序。

你可能感兴趣的:(读书笔记,《UNIX环境高级编程》)