OS X下UNIX环境高级编程(第三版)学习日志-第一章ChapterI,程序和进程

  1. 程序和进程

    程序是一个可执行文件,进程是程序的执行实例,unix系统中,每个进程都有一个唯一的数字标识符,被称为进程ID。

  2. #include "apue.h"
    
    int main(void){
        printf("hello world form process ID %ld\n",(long)getpid());
        exit(0);
    }

    重点:%ld表示打印长整型

    getpid()函数,返回自身的进程id,返回值类型为pid_t,如果要输出,可以(long)强转成长整型,使用长整型可以提高可移植性,推测:防止某个运行环境整型过短的情况发生。

  3. 进程控制

    有3个用于进程控制的主要函数:fork,exec,waitpid。

  4. #include "apue.h"
    int main(void){
        char buf[MAXLINE];
        pid_t pid;
        int status;
    
        printf("%% ");
        while(fgets(buf,MAXLINE,stdin)!=NULL){
            if(buf[strlen(buf)-1]=='\n')
                buf[strlen(buf)-1]=0;//replace the last char with null
            if((pid=fork())<0){
                err_sys("fork error");
            }else if(pid==0){   /*child*/
                execlp(buf,buf,(char *)0);
                err_ret("couldn't execute:%s",buf);
                exit(127);
            }
    
            /*parent*/
            if((pid=waitpid(pid,&status,0))<0)
                err_sys("wait pid error");
            printf("%% ");
        }
        exit(0);
    }

    该例程实现的功能是输入一个命令并执行,命令必须是$PATH指定的目录中存在的,且命令不接收参数。

    重点:

    fgets(buf,MAXLINE,stdin):从标准输入读入最大MAXLINE长度的内容到buf中,如果以换行符结尾,则将换行符替换为0(null),这是因为execlp要求的参数是以null结束而不是以换行符结束的。

    fork():创建一个新进程,新进程是调用进程的一个副本,称为子进程,fork对父进程返回进程id,对子进程则返回0(这段写的太模糊了。。。),调用一次,返回两次

    注释中写了一个/*child*/和一个/*parent*/,推测这分别是父进程和子进程的执行内容,个人理解此时有两个进程在工作,根据上文的写的“返回两次”,对子进程来说pid==0,那么执行/*child*/标注下的代码,对父进程来说pid==一个非负整数唯一标识,执行/*parent*/标注下的代码,等待子进程返回的结果。

    execlp(buf,buf,(char *)0):第一个参数表示执行的文件路径,第二个表示arg0,即第0个参数,(例子:ls -l:ls就是第0个参数,-l是第1个参数),man一下这个函数,原型中最后一个参数必须为(char *)类型的空指针,这个我也不知道为啥,百度百科的解释是:“如果用常数0来表示一个空指针,则必须将它强制转换为一个字符指针,否则将它解释为整形参数,如果一个整形数的长度与char * 的长度不同,那么exec函数的实际参数就将出错。”,也没说为啥出错。。。

    更重要的一点,如果函数调用成功,进程自己的执行代码就会变成加载程序的代码,execlp()后边的代码也就不会执行了。书里的解释是:用新的程序文件替换了子进程原先执行的程序文件。

    pid_t waitpid(pid_t pid, int *stat_loc, int options);返回子进程结束状态值。 子进程的结束状态值会由参数 status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数 status 可以设成 NULL。参数 pid 为欲等待的子进程识别码。

    在本例中,第二个参数为null,options为0,在子进程pid结束之前什么都不做。

    5.    线程和线程ID

    通常,一个进程只有一个控制线程(thread)——某一时刻执行的一组机器指令。

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

一点新的知识:返回值的接收者是进程,在unix中,产生(spawn)一个进程意味着1.创建一个pid,2.执行一个可执行文件,如果没有后者,那么只是一个空进程(其实不晓得理解的对不对)。

欢迎看到本文的朋友们与小弟交流,或者指正文中的错误,共同进步。

你可能感兴趣的:(c,unix,osx,process,Unix环境高级编程)