(由尚德)Linux系统编程学习一(第一第二讲:进程)

来源:互联网 发布:sns聊天软件 编辑:程序博客网 时间:2024/04/30 19:52

Linux系统编程学习一

第一讲  基础知识

posix标准
portale operating system interface for compputing system
对Linux发展到今天很重要

man手册
善于使用man


开发工具
Windows IDE

Linux下emacs,vi,gcc的组合


gcc选项

-c

-o

-wall

posix定义的数据类型
在头文件sys/types.h中定义

dev_t 包涵一个什么什么的宏,不明白,
uid_t,gid_t
pid_t
off_t 有符号整数,以字节为单位的偏移值,以字节为单位度量文件的大小
size_t  无符号整数,度量一个内存对象大小,字符串,数组缓冲区
只要是遵守posix标准的程序在类Linux中移植是没有任何问题的

头文件大多都是在/usr/include下,如果没有也会链接到此目录

系统调用的返回码

全局变量errno
perror(string)
strerror(errno)
错误一般返回一个负数


第二讲 进程

进程是理解文件与信号,作业控制关系访问权限以及其他大部分主题的基础

定义:进程是正在执行的程序

是整个Linux系统编程的基础

要重要掌握关键的概念和函数

内核跟踪进程的以下信息

运行的位置
访问的文件
信用状(安全机制)
当前目录
访问的内存空间

2.1 进程的属性

pid
信用状
setuid/setgid和系统守护进程
uid和gid总结

中间两方面需要对shell了解,看来学习shell的强大功能是不可避免呀

pid
基本属性pid-进程标识符和ppid-父进程,是唯一标识运行的进程,是一个正整数
pid_t getpid()
pid_t getppid()

创建进程的进程,是新进程的父进程
当一个进程退出的时候,会通知父进程,进程的退出信息会被保存
起来,保存到内核的进程表当中,到父进程请求

如果一个进程的父进程退出,子进程就成为一个孤儿进程,
都会变成init进程的一个子进程,
init的作用,收集父进程消亡的进程以及其退出状态,并通知内核
将子进程的信息从进程表中删除

例子

vi getpid.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc,const char **argv)
{
pid_t id=getpid();
printf("this is num %d/n",id);
return 0;
}

pid_t 是相当于一个整形的类型,专门用于pid格式

安全机制

采用unix的安全机制

etc/passwd,etc/group
int setgroups(size_t num,const gid_t *list)
int getgroups(size_t num,gid_t *list)

计算机用数字标识用户和组,并不关心真正的名字

做开发的时候,如果进程只属于一个组,想要访问不属于本组成员的时候
权限问题,补充组来解决此问题,每个进程有组组标识符,属于本组也
属于补充组,访问别的组的时候就不会出现权限问题

上面两个函数是对补充组操作的函数,要有root权限
set list指向标识符为num的数组,
get 获得进程属于补充组的列表,list指向数组,系统编程2.3讲 进程相关信息

程序参数

资源使用

建立使用限制

1,程序参数
    命令行参数:传递给程序的字符串 vi n.txt ls -l
    环境变量  :
    在启动的时候,就对程序可用
   
    int main(int argc,char * argv[])
    这是标准C,类Linux系统中标准main的原型
    argv[] 数组或指针
返回码:
  0,表示成功而退出
  1-127,表示出错而退出
  -1~-128内核异常终止保留的
 
  extern char *environ[] 直接访问全局变量---尽量少用
  const char * getenv(const char *name)----常用
 
  改变环境变量的函数
  int putenv(const char* string)----POSIX标准
  int setenv(const char* name,const char *value,int overwrite)
  ------BSD 标准
  如:
  putenv("PATH=/bin;/usr/bin")-----存在,更新
  setenv("PATH","/bin:/usr/bin",1)---表示修改
 
2,资源使用

一个程序的使用,是由内核所决定,如堆栈,代码段等。要对内核有深入的了解
获取资源使用情况的函数
    int getrusage(int who,struct rusage *usage)
        who: RUSAGE_SELF
             RUSAGE_CHILDREN
             RUSAGE_BOTH
        #include<sys/resource.h>
        struct rusage{
            struct timeval ru_utime;//执行用户代码的时间,包括请求的时间
            struct timeval ru_stime;//内核用来执行进程请求的全部时间,不包括阻塞时间
            long int ru_minflt;//进程造成的次要缺陷数
            long int ru_majflt;//进程造成的主要缺陷数
            long int ru_nswap;//进程的访问而从从磁盘调用内存的页面处
            .........
        };//用到的不多
        常用的就是这前五项
       
        这个函数返回结构体中的各个参数
       
       
3,建立使用资源限制  了解
       
        为了防止失控的进程,类Unix,设置限制,硬限制,软限制
       
        两个函数
        int getrlimit(int resource,struct rlimit *rlim)
        int setrlimit(int resource,const struct rlimit *rlim)
        struc rlimit
        {
            long int rlim_cur;//软限制
            long int rlim_max;//硬限制
        }
        RLIMIT_AS//进程可用内存的最大数量,堆栈,全局变量 动态内存
        RLIMIT_CORE//内核生成的CORE文件的最大大小
        RLIMIT_CPU//所用全部CPU时间,以秒计
        RLIMIT_DATA//数据存储的最大容量,以字节计
        RLIMIT_FSIZE//打开文件的最大数目
        RLIMIT_MEMMLOCK//
        RLIMIT_NOFILE//打开文件的最大速度
        RLIMIT_NPROC//进程可以产生的最大子进程数
        RLIMIT_RSS//可以随时使用的内存的最大容量
        RLIMIT_STACK//堆栈存储区的最大容量
       
        堆栈,理解,系统原理
       
       
4,进程的基本元素:很有用
        创建子进程
        等待子进程结束
        运行新程序
        终止
       
        回顾
        #include <unistd.h>
        pid_t fork();
        特别之处:返回两次
        子进程返回0
        不为0,子进程ID
        先后没有次序,是随机的
        pid_t是整型的数据结构
       
        例程:
         /*forkd.c*/
        #include <sys/types.h>
        #include <stdio.h>
        #include <unistd.h>
        #include <stdlib.h>
        int main(void)
        {
            pid_t child;
            if(!(child=fork()))
            {
                printf("in child /n");
                _exit(0);
            }
            printf("in parent --child is %d/n",child);
            return 0;

        }

    进程是一个正在执行程序   
       
  等待子进程结束
父进程当中,收集子进程的状态,称为等待

四种方法
内核调用 1
标准C函数库 3
        pid_t wait4(pid_t pid,int *status,int options,struct rusage *rusage);
        status//进程返回的状态,退出,Kill, 停止
        以下宏测试其状态
        WIFEXITED(status)//正常退出,内核返回,程序主动调用
        WEXITSTUTUS(status)//进程退出代码
        WIFSIGNALED(status)//进程被一个信号终止时 返回真值
        WTERMSIG(status)//f返回信号的号
        WIFSTOPPED(status)//为真,停止进程的信号
        WSTOPSIG(status)//返回停止进程的信号
        option 整形数据,控制调用怎样运行,运行的方式,
        rusage 指向一个结构体指针,检验进程资源使用信息,如果为0则不返回状态信息
        以下函数是wait4的子集
        pid_t wait(int *status)//返回之前,一直阻塞
        pid_t waitpid(pid_t pid ,int *status,int options)//
        //不返回资源使用信息
        pid_t wait3(int *status,int options,struct rusage *rusage)
        //不允许调用哪一个子进程被调用
       wait tomorrow 2.4 13min
      
      
       运行新程序
       exe函数簇
       execl
       execpl
       execle
       execv
       execvp
       execve
       运行成功没有返回,失败,返回-1,把原来的程序置换掉
      
       NULL表示结束, 没有NULL会造成段错误
       例程:
      
      
       终止:
       void exit(int exitcode);//标准C函数库
       void _exit(int exitcode);//系统调用
       //exitcode退出返回码
       int kill(pid_t pid,int signum);//signum信号,表示如何Kill
       //pid 大于0 就发送给当前进程标示符,如果不是则退出,返回错误码,
       如果小于-1,就返回给进程组ID及进程ID相反数的ID或组ID的所有进程
       如果0,发送当前进程所属进程组的所有进程
       如果是-1,信号就给发送给除了init进程的所有进程
      
2.5 进程4 简单子进程

system()
从进程读或写popen

通常创建一个子进程后,调用一个exec调用另外一个进程

system()
int sysytem (const char *cmd)
/bin/sh
示例

/*system*/

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

int main(void)
{
        int result;
        result = system("exec ls -l");
        if(!WIFEXITED(result))
        printf("abnormal exit/n");
        _exit(0);
}
不正常退出,会返回fail

特殊权限使用应谨慎

不使用系统守护进程和setgid setuid还是相对安全

从进程读或写
FILE *popen(const char *cmd,const char *mode)
int pclose(FILE *stream)
解决system不能解决的问题,如system不能解决希望读入另一个进程的数据
写到另外的一个进程
总之是对另外进程的操作的问题解决
不可同时读写,本函数是做不到的

返回为FILE指针,
失败返回NULL
调用结束用pclose,从wait4返回子进程的状态

第5点 进程的会话和进程组
会话
控制终端
进程组
孤儿进程

会话

每个会话都关联到终端,可以是本地的控制台,或者是映射到X window的伪终端

进程组
UNIX的最初是建立工具的集合

孤儿进程组
多个进程组构成一个会话
当会话消失时,会话组长退出时,会话组不能使用标准输入输出,终端
已经退出了,

回顾

 

 

原创粉丝点击