• 操作系统 Linux操作系统编程开发


    Linux操作系统编程开发

    预备知识:

      1、进程操作:Linux系统是多任务的操作系统,采用进程作为任务调度的单位,进程在Linux系统下的概念是程序代码的一次执行,包括运行的代码和运行需要的数据、参数等资源。

      2、进程和程序的区别:一方面:在Linux系统下,进程是程序代码的执行,所以程序是一段运行的,有生命力的程序,是一个动态的概念;一个程序是指储存在磁盘或者其他存储介质中的静态代码。另一方面:一个进程是基于一个程序运行的,而一个程序可以被重复载入到内存,形成多个进程!

      3、CPU时间片(Linux系统大约1ms):时间片即CPU分配给各个程序的时间,每个线程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。

      4、Linux系统中进程在宏观上是并行,在微观上是串行的(一个CPU)。在宏观上是并行:同时可以打开多个进程;每个进程都有一个时间片和优先级。在微观上是串行:在每一个CPU时间片中,每个进程都有机会运行,优先级高的进程被运行的概率更大。如果时间片结束,进程还在运行,CPU将剥夺并分配给另一个进程;如果进程在时间片结束之前结束或者进入阻塞状态,CPU立即进行切换!一个CPU,一次只能执行程序的一部分。

      5、mmu和多进程系统:

      6、PID(进程号Process ID):在Linux系统中,每个进程都有一个进程号(PID),所有的进程使用树状结构组织。Linux系统启动时第一个进程是根进程该进程进一步调用系统其它进程。Linux系统中,进程之间有一个明显的继承关系,所有进程都是 PID 为1的 init 进程的后代。

      7、父进程和子进程:Linux系统中每个进程必有一个父进程,相应的,每个进程也可以由零个或者多个子进程。拥有同一个父进程的所有进程被称为兄弟。进程之间的关系存放在进程描述符 task_struct 中。每个 task_struct 都包含一个指向其父进程 task_struct 的指针 parent,还有一个被称为 children 的子进程链表。  

      8、一个线程可以创建和撤销另一个线程,同一个进程中的多个线程并发运行

      9、现存进程、交换进程、init进程、精灵进程

      10、僵尸进程、孤儿进程

      11、进程环境:

      12、进程描述符:

      13、组识别码(gid-Group ID):每个登录的用户至少都会取得两个ID,一个是用户ID(UserID,简称UID),一个是用户组ID(Group ID,简称GID);每一个文件都会有所谓的所有者ID与用户组ID。

      14、PCB(progress control block-进程控制块),系统通过PCB,描述进程和控制进程。在Linux系统下,PCB是 task_struct结构体

      15、进程内存分配示意图(32位操作系统):内核空间和用户空间,内核空间则为所有进程以及内核所共享

      

    Linux操作系统进程函数:

    1、fork/vfork创建子进程

    2、exec系列函数execv/execl、execp/execlp、execve/execle;用exec函数可以把当前进程替换为一个新进程,且新进程与原进程有相同的PID,它将进程创建与加载一个新进程映象分离

      int execl(const char *path, const char *arg, ...);

      int execlp(const char *file, const char *arg, ...);

      int execle(const char *path, const char *arg, ..., char * const envp[]);

      int execv(const char *path, char *const argv[]);

      int execvp(const char *file, char *const argv[]);

      int execve(const char *path, const char *argv[], char * const envp[]);

    说明:

    path参数表示你要启动程序的名称包括路径名

    file参数表示命令的文件名

    arg参数表示启动程序所带的参数,一般第一个参数为要执行命令名,不是带路径且arg必须以NULL结束

    argv参数是需要传递给命令的参数,该数组以NULL结束

    envp参数是环境变量数组

    3、getpid、getppid:获取进程码

    4、setpgid:设置指定进程的组识别码;getpgid:获取指定进程组识别码;(setpgrp、getpgrp是参数为0的特殊情况)

    5、setpriority:设置指定进程、进程组、用户的优先级别;getpriority:获取指定进程(进程号)、进程组(识别码)、或者用户(用户ID)的优先级,优先级是-20~20之间的整数,数值越大优先级越高

    6、wait/waitpid:暂停当前进程,等待子进程的中断或结束。wait、参数说明pid_t wait(int *status),status保存子进程中断或结束的状态,可设为NULL,返回值为中断或结束的子进程的进程号。waitpid参数说明pid_t waitpid(pid_t pid,int *status,int options) pid:-1表示任何子进程,0:组识别码相同的所有子进程;status保存子进程中断或结束的状态,可设为NULL;options;0;WNOHANG(若无子进程结束则立即返回)、WUNTRACED(若子进程暂停则立即返回);WNOHANG | WUNTRACED(两者取或),

    7、进程终止函数:

      _exit:直接使进程停止运行,清除其使用的内存空间,并清除其在内核的各种数据结构。exit() 函数与 _exit() 函数的最大区别在于exit()函数在调用exit系统调用前要检查文件的打开情况,把文件缓冲区中的内容写回文件,也就是“清理I/O缓冲”。

      atexit:ISO C的规定,一个进程可以登记多至32个函数,这些函数将由exit自动调用,这些函数为被称为终止处理函数,并调用atexit函数来登记这些函数。

      on_exit:

     

    Linux操作系统信号量及操作函数:

    预备知识:

    0、临界区同一时刻只能有一个进程执行其中代码的代码段。死锁:某个进程修改了信号量而进入临界区之后,因为崩溃或被“杀死(kill)",却而没有退出临界区,其他被挂起在信号量上的进程永远得不到运行机会。

    1、资源互斥和资源同步。资源互斥:指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性,例如死锁:进程甲占用资源A,申请资源B,进程乙占用资源B,申请资源A就会造成一种资源互斥情况“死锁”;资源同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问

    2、相交进程之间的关系主要有两种,同步与互斥。

    3、处理资源的互斥与同步的几种方式: 自旋锁,信号量,互斥锁与原子变量

     4、信号量是一种能够有效处理进程之间资源互斥和同步的锁机制,信号量是一个计数器一个信号量表示可用资源的个数。信号量的两种操作,P和V:P,等待信号量,当信号量值为0时,程序等待;当信号量值大于0时,信号量减1,程序继续运行(进程运行需要资源)。V,发送信号量,将信号量值加1,(产生资源的进程)

    5、Linux系统下的通讯机制(IPC):管道、消息队列、信号、信号值、共享内存(最快的IPC方式)、共享映射文件、套接字(不同机器之间的进程进行通讯)等。

    6、信号量集合机制多个进程(队列结构)要分别获得多个临界资源(信号量数组)后方能运行,这就是信号量集合机制。如果进程被挂起,Linux 必须保存信号量的操作状态并将当前进程放入等待队列(sem_queue)。

    7、线程占用的资源共享的内存,匿名管道,malloc出来的空间、socket描述符、epoll描述符和线程锁等。

    注:2019年10月26日18:07:53,线程的资源是指那些?资源和虚拟内存的关系是什么?为什么资源不能同时被不同的进程占用,而要释放呢?不能通过不同的进程使用不同的指针调用,而且每个进程的虚拟空间(除去共享的内核空间)都是独立的,将程序加载到内存中,然后放入寄存器中,这个加载到的内存不是独立的码?那倒是因为寄存器是唯一的,所以会有资源互斥?个人理解,数据结构实现上,信号是通过字典,键和值是信号集。

    8、信号量的数据结构(sem):

    struct sem {
    
      int  semval;         /* 信号量的当前值  */
    
               int   sempid;         /*在信号量上最后一次操作的进程识别号 *                    
    
            };

    9、信号量集的数据结构(sem_ds):

    struct semid_ds {
    
      struct ipc_perm sem_perm;          /*  IPC权限 */
    
       long        sem_otime;        /* 最后一次对信号量操作(semop)的时间 */
    
      long        sem_ctime;        /* 对这个结构最后一次修改的时间 */
    
      struct sem      *sem_base;      /* 在信号量数组中指向第一个信号量的指针 */
    
       struct sem_queue *sem_pending;       /* 待处理的挂起操作*/
    
      struct sem_queue **sem_pending_last; /* 最后一个挂起操作 */
    
      struct sem_undo *undo;          /* 在这个数组上的undo 请求 */
    
      ushort          sem_nsems;           /* 在信号量数组上的信号量号 */
    
       };

    10、系统中每一信号量集合的队列结构(sem_queue

    struct sem_queue {   
    
        struct sem_queue * next;   /* 队列中下一个节点 */
    
        struct sem_queue **    prev;   /* 队列中前一个节点, *(q->prev) == q */
    
        struct wait_queue *    sleeper;    /* 正在睡眠的进程 */
    
        struct sem_undo *  undo;   /* undo 结构*/
    
        int            pid;    /* 请求进程的进程识别号 */
    
        int            status; /* 操作的完成状态 */
    
        struct semid_ds *  sma;    /*有操作的信号量集合数组 */
    
        struct sembuf *    sops;   /* 挂起操作的数组 */
    
        int    nsops;  /* 操作的个数 */
    
    };

    11、三种数据结构的关系

     

    信号量操作的函数(系统调用):

    1、semget ( key_t key, int nsems, int semflg ),创建并打开一个信号集

    2、semop ( int semid, struct sembuf *sops, unsigned nsops),根据索引值,对指定的信号量进行指定的操作(P、V操作)

    一、sops参数指向类型为sembuf的一个数组

    struct sembuf {
    
                    ushort  sem_num;        /* 在数组中信号量的索引值 */
    
                    short   sem_op;         /* 信号量操作值(正数、负数或0) */
    
                    short   sem_flg;        /* 操作标志,为IPC_NOWAIT或SEM_UNDO*/
    
            };

    注:1、sem_op为负数,那么就从信号量的值中减去sem_op的绝对值,这意味着进程要获取资源如果sem_op是正数,把它的值加到信号量,这意味着把资源归还给应用程序的集合

    命令(cmd)

    解   释

    IPC_STAT

    从信号量集合上检索semid_ds结构,并存到semun联合体参数的成员buf的地址中

    IPC_SET

    设置一个信号量集合的semid_ds结构中ipc_perm域的值,并从semun的buf中取出值

    IPC_RMID

    从内核中删除信号量集合

    GETALL

    从信号量集合中获得所有信号量的值,并把其整数值存到semun联合体成员的一个指针数组中

    GETNCNT

    返回当前等待资源的进程个数

    GETPID

    返回最后一个执行系统调用semop()进程的PID

    GETVAL

    返回信号量集合内单个信号量的值

    GETZCNT

    返回当前等待100%资源利用的进程个数

    SETALL

    与GETALL正好相反

    SETVAL

    用联合体中val成员的值设置信号量集合中单个信号量的值

  • 相关阅读:
    常用地址
    三步搭建Spring Cloud 服务注册
    Java判断两个时间段是否有交集
    CentOS-7下安装docker
    linux 版菱形
    《少林问道》
    Linux下安装Nginx详细图解教程
    测试
    CentOS修改主机名和主机表
    虚拟机中CentOS配置静态网络
  • 原文地址:https://www.cnblogs.com/yinminbo/p/11736038.html
Copyright © 2020-2023  润新知