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

本文介绍Linux系统编程的基础知识,涵盖POSIX标准、开发工具选择、关键数据类型、系统调用及错误处理等内容,并深入探讨了进程的概念、属性、管理及与文件、信号的关系。

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的最初是建立工具的集合

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

回顾

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值