4IO进程


DAY 1 


【1】IO







文件:是文件系统中管理磁盘上的数据的一个基本单位
      struct   file结构体
      
      
      
      struct   node结构体     
      
      
      (1)文件描述符     
      (2)文件指针
    注意:后续操作文件指针和文件描述符就是对文件进行操作
找文件:
    /home/linux/file            
    
    filename 若果不加路径,默认是对当前目录


【2】Linux文件类型
    b  c   d   -   l   s   p


(1)-   常规文件(普通文件)
     a、文本文件,用来存储字符数据的
     b、二进制文件:
(2)d   目录文件:用来存储子目录或者文件的名字


(3)l   链接文件


(4)p   管道文件:帮助用户程序找到内存某块区域(内核空间)


(5)s   套接字文件:  用来实现通信(本地通信和网络通信)


(6)c   字符设备文件


(7)b   块设备文件


【3】标准IO


标准IO:  是c语言标准库中实现的用于输入和输出的函数,用c标准库写好
          用户程序具有可移植性
          
          
操作对象:  文件指针,是一个结构体指针     FILE  *  




缓冲区:
       (1)全缓冲:针对文件
             
             a、大小是4096字节
             b、程序正常结束
             c、fflush函数
             
       (2)行缓冲:针对终端       标准输入stdin、标准输出   stdout


             a、大小是1024字节
             b、程序正常结束
             c、fflush函数
             d、\n
                                  
       (3)无缓冲:针对终端         标准出错  stderr
       
【4】操作文件的基本流程      


(1)创建或者打开文件


    fopen
     FILE *fopen(const char *path, const char *mode)
     功能:创建或者打开文件
     参数:
          path   指向文件的名字  “filename”   或者 argv[1]  argv[2] 
          mode   代表对文件的操作方式
                   r      Open text file for reading.  The stream is positioned at the beginning of the file.
                          打开文件,对文件进行读操作,从文件开始位置读取
                          
                   r+     Open for reading and writing.  The stream is positioned at the beginning of the file.
                          打开文件,对文件进行读写操作
                          
                   w      Truncate  file  to  zero  length  or  create text file for writing.  The stream is positioned at the
                          beginning of the file.
                          如果文件不存在,则会创建,对文件进行写操作
                          如果文件存在,则会清空文件原有内容
                   w+     Open for reading and writing.  The file is created if it does not exist, otherwise it is  truncated.
                          如果文件不存在,则会创建,对文件进行读、写操作
                          如果文件存在,则会清空文件原有内容                         The stream is positioned at the beginning of the file.


                   a      Open  for appending (writing at end of file).  The file is created if it does not exist.  The stream
                          is positioned at the end of the file.
                          如果文件不存在,则会创建文件,从文件末尾位置追加写入
                          如果文件存在,则会从文件末尾位置追加写入
                   a+     Open for reading and appending (writing at end of file).  The file is created if it does not  exist.
                          The initial file position for reading is at the beginning of the file, but output is always appended
                          to the end of the file.
                          如果文件不存在,则会创建文件,从文件末尾位置追加写入,从文件开头读取数据
                          如果文件存在,则会从文件末尾位置追加写入,从文件开头读取数据
        返回值:
              成功   FILE*
              失败  NULL(判断条件)
              
              fopen("filename", "r")
              fopen(argv[1], "r")
                       
    
(2) 文件操作:   读、  写、  文件位置定位


      a、每次操作一个字符
        fgetc /  fputc
         int fgetc(FILE *stream);
         功能:  从文件指针关联的地方(文件、终端)读取数据
         参数:
              stream   表示要读取的文件或者终端
         返回值:
              成功   读取的字符数据
              失败   EOF(-1)  可以用来作为判断读取文件结束的条件
              
         int fputc(int c, FILE *stream); 
         功能:  往文件或者终端写入数据
         形参:
              c   表示要写入的字符数据
              stream   终端或者文件
         返回值:
              成功   写入的字符
              失败   EOF(-1)
              
         
         
           
        
      b、每次操作一行字符
      fgets /  fputs
      
      char *fgets(char *s, int size, FILE *stream);
      功能:  从stream关联的终端或者文件中读取数据
      参数:
          s   指向用户开辟的缓冲区(定义一块空间)
          size  表示用户想要读取的数据是多少?
          stream   终端或者文件
      返回值:
          成功  返回读取的数据
          失败  NULL (并且可以作为结束的标志)
          
          【注意】
            \n    当一行中的数据小于size,此时会读取到\n就结束
            \0    当读取的数据小于一行的中的数据时,此时只会读取size-1,
                  并且最后一个字符用\0代替。
                  
        int fputs(const char *s, FILE *stream);           
        功能:  往终端或者文件中写入数据
        参数:
               s   事先在用户程序中开辟缓冲区,缓冲区中有数据
               stream   文件或者终端
        返回值:
                成功   非负数
                失败   EOF(-1)
                
                
                
 --------------------------------------------------------------------------------     
      c、可以操作纯字符数据或者也可以操作二进制数据
      fread /  fwrite
      size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
      功能: 从文件或者是终端读取数据
      参数:
              ptr   用户开辟的缓冲区,用来存放数据
              size  每个对象的大小是多少?
              nmemb 对象个数是多少?
              stream 从终端或者文件读取数据
              
     返回值:
             成功   读取的对象个数是多少?
             失败   读取到文件结束时,返回值  0,把0作为判断条件
             
      size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
      功能: 往文件或者是终端写入数据
      参数:
              ptr   用户开辟的缓冲区,用来存放数据
              size  每个对象的大小是多少?
              nmemb 对象个数是多少?
              stream 往终端或者文件写入数据
              
     返回值:
             成功   写入的对象个数是多少?              
      
 ------------------------------------------------------------------------------------     


      void rewind(FILE *stream);
      功能:  重新定位文件的位置,放到开头位置
      参数:  
            stream   代表对那个文件进行位置定位   
      返回值:无
      
      long ftell(FILE *stream);
      功能:  获取当前文件的位置指针在那个地方?
      参数:  
            stream   要操作的那个文件是什么?  
      返回值:
            文件位置的当前值是多少,用数字表示位置
            
      
      fseek(重点)
      int fseek(FILE *stream, long offset, int whence)
      功能:  文件位置定位函数
      参数:
            stream   表示对那个文件进行位置定位
            whence  基准点 , 表示要从那个地方开始偏移
                     SEEK_SET  表示开头位置
                     SEEK_CUR  表示当前位置
                     SEEK_END  表示末尾位置
           offset   偏移量  
                      正数   表示往文件末尾位置偏移多少个字节
                      零     一动不动
                      负数   表示往文件的开头位置偏移多少个字节
      
      返回值:
            成功   0
            失败   -1
            
            fseek(fp, 5, SEEK_SET);
            fseek(fp, 0, SEEK_SET);
            
            fseek(fp, -5, SEEK_SET);(错误)
            
            fseek(fp, 5, SEEK_CUR);
            fseek(fp, 0, SEEK_CUR);
            fseek(fp, -5, SEEK_CUR);
            
            fseek(fp, 5, SEEK_END);
            fseek(fp, 0, SEEK_END);
            fseek(fp, -5, SEEK_END);            
            
      
      
(3)关闭文件
      fclose
      
      
      

      DAY 2


【1】time              man  2 time   、    man    3   localtime


        #include <time.h>


       time_t time(time_t *t);
        功能:  获取时间值
        参数:  
            t   用来指向用户空间的指针变量,需要用户自己开辟time_t空间
        返回值:
              成功   时间值
              失败   -1
              
        struct tm *localtime(const time_t *timep);      
        功能:把秒数装换成年月日时分秒的形式
        参数:
              timep  指向time_t类型的变量
       返回值:
            返回的时间值
            
            struct tm {
               int tm_sec;         /* seconds */
               int tm_min;         /* minutes */
               int tm_hour;        /* hours */
               int tm_mday;        /* day of the month */
               int tm_mon;         /* month */
               int tm_year;        /* year */
               int tm_wday;        /* day of the week */
               int tm_yday;        /* day in the year */
               int tm_isdst;       /* daylight saving time */
           };


            
【2】 


文件IO:
      由操作系统提供用于输入输出的函数,不同类型的文件都可以读取
      标准IO只能在用户空间使用(0~3G-1)
      文件IO可以在用户空间或者内核空间中使用
      
操作对象:
      文件描述符是一个非负的整数,在应用层当用用于联系文件的一个对象
      0 、 1、 2剩下的其他描述符,从最小的数值开始分配




缓冲区:无缓冲


-------------------------------------------------------------------------
标准IO是对文件IO的一个封装,并且012三个文件描述符不需要定义,直接可以使用
stdin  ---   0
stdout ---   1
stderr ---   2






【3】文件操作流程
(1)创建或者打开文件
      open
      
      
      
      权限值可以被进程umask修改,文件权限掩码屏蔽位
      
      0666原本文件权限
          1  1  0      1   1   0      1  1   0
      
      umask值0002
      
          0  0  0      0   0   0      0   1   0
          1  1  1      1   1   1      1   0   1
      
      
 文件权限 1  1  0      1   1   0      1   0   0


       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>


       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);
       功能:打开文件或者创建文件
       参数:
            pathname     文件名字
            flags        标志位
                         O_RDONLY  只读
                         O_WRONLY  只写
                         O_RDWR    可读可写(这三者只能选择其中之一)
                         
                         O_CREAT   创建文件
                         O_EXCL    防止重复创建文件
                         O_TRUNC   创建文件时,清空文件原有内容
                         O_APPEND  追加写入文件
            mode         0664
        返回值: 
            成功    文件描述符   
            失败    -1, 并且会设置错误码errno(全局变量)
 
等价形式:            
       r          ---               O_RDONLY
       r+         ———               O_RDWR
       
       w          ---               O_WRONLY | O_CREAT | O_TRUNC
       w+         ---               O_RDWR   | O_CREAT | O_TRUNC               
       
       a          ---               O_WRONLY | O_CREAT | O_APPEND
       a+         ---               O_RDWR   | O_CREAT | O_APPEND                     


        void perror(const char *s);
        功能: 打印标准的错误信息
        参数:
             s   指向字符串,需要用户自己定义,后面会跟上冒号空格和标准
                  的错误信息加上换行
        返回值: 无
        
        
        
 
(2)读、写、文件位置定位
      read、 write、 lseek
      
      ssize_t write(int fd, const void *buf, size_t count);
      功能:  往终端或者文件中写入数据
      参数:
          fd   表示终端或者文件
          buf  指向的缓冲区
          count 表示用户要求写入的字节数
      返回值:
          成功  表示实际写入的字节数
          失败  -1
      
      
      off_t lseek(int fd, off_t offset, int whence);
      功能:  设置文件操作位置
      参数
          fd      文件
          whence  基准点
          offset  偏移量
     返回值:
          成功   返回当前位置到文件开头的字节数是多少个?
          失败   -1
        
      
(3)关闭文件
      close
                   
-------------------------------------------------------
【4】目录


操作流程:
1、打开目录opendir
    DIR *opendir(const char *name);
    功能:  打开目录
    参数:
          name   表示目录的名字
    返回值:
          成功   DIR*
          失败   NULL
          
2、读取目录readdir
    struct dirent *readdir(DIR *dirp);
    功能:  读取目录下内容(子目录的名字和文件的名字)
    参数:
          dirp   指向打开的目录
    返回值:
          成功  读取的文件信息
          失败  NULL(同时还是判断读取目录结束的标志)
    
    
3、关闭目录closedir
    int closedir(DIR *dirp);
    功能:  关闭目录操作
    参数: 
     dirp   表示通过opendir打开的目录
    返回值:
            成功   0
            失败   -1


    
    chdir    mkdir


-------------------------------------------------
【5】获取文件属性信息stat
    int stat(const char *path, struct stat *buf);
    功能:       获取文件属性信息
    参数:
        path     文件的名字
        buf      把文件的信息存储在buf指向的空间中
                 事先定义一个strcut  stat  类型结构体变量
    返回值:
          成功   0
          失败   -1














课外知识点:
  安装追踪工具:ctags
 1、 在线安装:  sudo  apt-get  install  ctags
      追踪数据类型\宏定义
      vi  -t  (EEXIST)
      
 2、 进入/usr/include目录下,生成索引文件tags
     sudo ctags  -R
     
     
     
     typedef
     define
     ctrl + ] 往后追踪    ctrl + t  往前追查
     退出  q
     
 3、 打开sudo  vi   /etc/vim/vimrc文件,然后在文件的末尾位置
      添加一行代码
      set  tags=/usr/include/tags




DAY 3




【1】库


(1)为什么?
    提高项目开发的效率


(2)什么?
    库就是一个经过编译之后的二进制文件,可以执行,但是不能单独执行,
    由源代码文件生成二进制文件
    
(3)分类,从编译或者执行的时间来区分静态库或者动态库


    静态库:在编译的时候,把库中被调用的函数代码添加到可执行程序中,
            可执行程序代码变大,运行效率高
    
    动态库:在编译的时候,只是把要调用函数符号添加可执行程序,运行
            可执行程序的 的时候,才回去内存中调用库中的代码,动态库
            大小几乎没变。运行效率低(共享库)


(4)制作库
      a、确定功能模块,把函数形参返回值确定
          
          int add(int a, int b)
          {
            return a+b;
          }
          
      b、库都是由.o文件组成,事先生成.o文件
      
          gcc  -c   add.c  -o add.o   静态库
          
          gcc  -fPIC  -c   add.c  -o add.o   共享库
          
                —fPIC   表示位置独立代码,可以别加载到内存共享区域
                        的任意一个位置执行,如果不加这个参数,则是
                        使用绝对地址形式,把共享库放到固定地址这个
                        
      c、制作库
      
         静态库:
                ar   制作静态库的指令
                -crs   c --> 创建  r --> 插入   s -->  索引
                libadd.a     制作库都是以lib,加上库名字,在.a结尾
                ar  -crs  libadd.a  add.o 
          
         动态库:
         
                gcc  -shared   add.o -o  libmath.so
               
      d、写好可执行程序,在编译或者执行添加代码
         -L  指定路径  -l  指定库的名字
         gcc  main.c  -o main   -L  .   -ladd




         【注意】动态的加载方式
         (1)拷贝共享库到/lib或者/usr/lib
         sudo cp libmath.so /lib
          (2) 设置全局环境变量的方式
          export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/linux/17041/day3/dymaic
          export LD_LIBRARY_PATH=    表示环境变量清空操作


-------------------------------------------------------------------------------
【1】进程
(1)为什么
    a、多任务
    b、执行效率


(2)什么是?


    程序  进程
    
    
    进程是描述程序的一次执行,把一个 程序执行多次会执行多个进程
    程序和进程并不是一一对应
    操作系统为每一执行的程序分配一个结构体struct  task_struct
    软件方面:pid  进程标识符,唯一的表示一个进程
    
              state  状态
              
              
    硬件方面:
  
    
    
    操作会为进程分配资源和地址空间(4G),
    是不是操作系统的最小单位?
    
    进程是资源分配的最小单位,但不是执行的最小单位
    
    
(3)进程的组成
    
      代码段、  数据段   内核数据段
      
      
(4)进程类型
      a、交互进程
      
          前台进程:  既可以输入也可以输出
          
          后台进程:  只允许输出不允许输入   &
          
      b、批处理进程
      
      c、守护进程


(5)进程状态
      man  ps
      
      
       D    uninterruptible sleep (usually IO)
            不可中断睡眠态或者阻塞态
            
       R    running or runnable (on run queue)
            正在运行   或者   准备运行
            
       S    interruptible sleep (waiting for an event to complete)
            可中断的睡眠态或者阻塞态
            
       T    stopped, either by a job control signal or because it is being traced.
            暂停
                 
       X    dead (should never be seen)
            死亡态
            
            
       Z    defunct ("zombie") process, terminated but not reaped by its parent.
            僵尸态
            子进程结束了,而父进程并没有回收子进程所占用的资源,此时这个
            子进程就属于僵尸进程,状态属于僵尸状态
            
            
            
       For BSD formats and when the stat keyword is used, additional characters may be displayed:
       <    high-priority (not nice to other users)
       N    low-priority (nice to other users)
       L    has pages locked into memory (for real-time and custom IO)
       s    is a session leader管理或者控制进程
       
       l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
       
       +    is in the foreground process group.




(6)ps   -ajx          更偏向于查看pid值


      top
      
      kill 


-------------------------------------------------------------------
【4】进程编程




(1)创建进程
      a、fork
      
      pid_t fork(void);
      功能:  在调用进程用产生一个进程(子进程)
      返回值:
            成功  在父进程中返回子进程pid值,在进程中返回值0
            失败  -1
            
            
      pid_t getpid(void);
      功能:  获取当前调用getpid函数的那个进程的pid值
      
      pid_t getppid(void);
      功能:  获取当前调用getppid函数的那个进程的父进程pid值
      
      
      b、exec函数族
      
      
(2)结束进程
      void _exit(int status);
      功能:  结束一个正在运行的进程
      参数:
          status  是一个退出的状态值,传递0 (正常结束程序)
                  或者  1(程序出错时,结束程序)




      void exit(int status);
      功能:  结束一个正在运行的进程
      参数:
          status  是一个退出的状态值,传递0 (正常结束程序)
                  或者  1(程序出错时,结束程序)      
      
      两者区别在于_exit不会刷新缓冲区中的数据,而exit会刷新数据
 --------------------------------------------------------------------
 孤儿进程:
          父进程结束的时候,子进程还没有结束,此时子进程属于孤儿进程,
          并且会移交给1(init)号进程
 
 僵尸进程:
          子进程结束的时候,父进程还在运行,但是父进程并没有回收子进程
          所占用的任务结构体和地址空间,此时子进程属于僵尸进程,此时
          的状态属于僵尸状态(Z),需要调用wait家族函数进行资源的清理操作
    
      
(3)进程资源的清理
       pid_t wait(int *status);
       功能:  等待任意子进程状态的结束
       参数:
       
            status    接收子进程eixt函数退出时的状态是正常还是失败退出
       返回值:
              成功:结束的子进程pid值
              失败  -1
             



DAY 4





【1】exec函数族


       (1)int execl(const char *path, const char *arg, ...);
       功能:在一个程序中调用另外一个新的程序,用新的程序把原有程序
              的代码替换掉
       参数:
          path   用来指定可执行程序的名字,要求可执行程序的路径
                  必须是绝对路径  "/bin/ls"  
                  
         arg     可执行程序的名字   ls
         
         arg     -l    或者“-la”
         
         arg     -a
         
         NULL    注意:一定要以NULL作为参数的结束
         
         
        返回值:
            失败   -1
      
      
         
       (2)int execlp(const char *file, const char *arg, ...);
       
       参数:
          path   用来指定可执行程序的名字,要求可执行程序的路径
                  是相对路径  "/bin/ls"  
                  
         arg     可执行程序的名字   ls
         
         arg     -l    或者“-la”
         
         arg     -a
         
         NULL    一定要以NULL作为参数的结束
         
         
       返回值:
            失败   -1
      
【2】守护进程


    (1)什么?
            守护进程是一个后台的服务进程,这个进程运行周期是从系统启动的时候
            开始运行,系统结束的时候终止
             
    (2)特点
            (1)不受终端控制,
            (2)做服务用,具体服务依据程序要求
    
    (3)守护进程的创建步骤


          (1)创建父子进程,让父进程结束


                fork ()    exit
          (2)完全摆脱终端控制,脱离会话组和进程组
                setsid()
                pid_t setsid(void);
                功能:  成为会话组和进程组的额组长完全摆脱终端控制
                
                
          (3)改变当前目录为根目录
                chdir()
                int chdir(const char *path);
                功能:  改变目录   chdir("/")
                
          (4)重设文件权限掩码
                umask()
                        umask(0)   umask(0002)
                        
          (5)关闭所有打开文件描述符
                close()
          
                for(i = 0; i < 1024; i++)
                {
                    close(i);
                }
          
          (6)守护进程的服务操作,由于守护进程生命周期是系统结束时终止,所以第六步必须处于
                循环状态
          
【3】线程
    (1)为什么?
          (1)能够执行多任务处理,实现并发执行,能够同时执行多个程序
          (2)执行效率提高
          (3)资源分配  线程间切换所需要的时间跟进程有区别
    (2)什么?轻量级的进程,也可以被cpu、调度执行
    
     线程跟线程间通信,必须采用   【全局变量】
     
【4】
      (1)线程   创建 pthread_create
                  
         #include <pthread.h>


         int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                            void *(*start_routine) (void *), void *arg);
           
           
         参数:
              thread    表示线程号,用来标识一个线程
              attr      线程属性指针变量,描述一个线程所需要的栈空间  8M
                        默认  NULL
              
              start_routine  函数指针变量,用来指向一个函数
                              void* pthread_fun(void *arg)
                              
              arg       把pthread_create的第四个参数传递给了函数指针变量的所指向的函数的形参
              
         返回值:
                成功  0(0作为判断条件)
                失败  错误码
              
            
                  
      (2)线程   结束
                   pthread_exit
           void pthread_exit(void *retval); 
           功能:   结束线程
           参数:  
                  retval    线程退出时的状态
           返回值:无
           
           
           
                   
      (3)线程   资源回收
                  pthread_join 
          int pthread_join(pthread_t thread, void **retval);
          功能:用来等待线程退出,如果等待不到,则调用pthread_join函数的线程
                会在次一直阻塞,直到等待指定的线程退出
          参数:
                 pthread  表示要等待的线程
                 retval   表示要接收pthread_exit的退出状态
          返回值:
                成功  0(判断标志)
                失败  错误码
          
【5】同步  与  互斥       机制
          
           
      (1)共享资源  :  可以被多个进程或者线程访问的资源
      
      (2)临界区    :  可以被访问的共享资源之间的那段代码
      
      (3)同步      :  就是多个线程或者进程按照约定的先后顺序共同完成一件事情
      
      (4)互斥      :  只能允许一个进程或者线程访问临界区
          
          
【6】信号量


      信号量理解为一个资源,在系统使用一个 变量  来表示这个资源
  
      (0)初始化一个信号量资源sem_init    初始化信号量的数量
       #include <semaphore.h>


       int sem_init(sem_t *sem, int pshared, unsigned int value);
       功能:  用来初始化一个信号量资源,并且设置信号量资源的额数量是多少个?
              (依据程序需要,自己事先分析程序)
      参数:   
            sem        表示信号量资源
            pshared    在进程还是在线程之间共享
                        0   表示在线程中使用
                        1   表示在进程中使用(具有亲缘关系的进程)
            value      信号量的数量是多少个?
       返回值:
             成功  0
             失败  -1
             
            
      (1)申请操作p           sem_wait    减 1
        int  sem_wait(sem_t *sem)
        功能:  申请信号量 ,执行一次操作  减 1
        参数:  
                sem  表示申请哪个信号量
        返回值:
            成功  0
            失败  -1
        
        
      (2)释放操作v           sem_post    加 1
        int  sem_post(sem_t *sem)
        功能:  释放信号量 ,执行一次操作  加 1
        参数:  
                sem  表示释放哪个信号量
        返回值:
            成功  0
            失败  -1          
       
        
        
        
        

 DAY 5

【1】互斥锁
    sudo  dpkg  -i  *.deb
    
(1)原因
     用互斥锁这个机制保护共享资源,一个线程访问的时候,其它
     不允许访问共享资源,这样达到互斥的目的
     
     互斥锁也是一个资源需要申请或者释放
     
     如果一个线程申请到了互斥锁,其他的线程只能等待(阻塞),只能申请互斥
     锁的线程释放之后,其它线程才可以继续申请。
     
(2)pthread_mutex_init
       int pthread_mutex_destroy(pthread_mutex_t *mutex);
       功能:释放掉一把锁,把创建锁时的一些信息清理掉
       参数:
            mutex    代表那把锁(资源)
       
       int pthread_mutex_init(pthread_mutex_t *restrict mutex,
              const pthread_mutexattr_t *restrict attr);
       功能:初始化一把锁
       参数:
            mutex   代表那把锁(资源)
            attr    代表在一个进程中使用还是在不同的进程中使用 
                    NULL
                    
(3)申请或者释放锁
      int pthread_mutex_unlock(pthread_mutex_t *mutex);
      功能:  释放锁,释放锁之后其它线程可以去申请锁
      
      int pthread_mutex_lock(pthread_mutex_t *mutex);
      功能:申请锁操作,如果一个线程申请到了,其它不能再去申请锁,
            其它线程处于阻塞状态
      参数:  mutex   初始化的那把锁(资源)


【2】条件变量


    条件变量是一种信号通知方式,如果一个线程发送信号之后,其它的线程
    可以判断是否信号到来,接收到信号,则从接收信号的位置之后,继续往
    下运行,如果没有,接收到信号,则在接收信号的地方阻塞。


    一个线程状态发生变化时,通知另外一个线程执行处理操作
    
    (1)int pthread_cond_destroy(pthread_cond_t *cond);
        功能:        销毁一个条件相关的数据结构信息
        参数:
              cond   条件变量
        返回值:
              成功    0
              失败    错误码
               
       int pthread_cond_init(pthread_cond_t *restrict cond,
              const pthread_condattr_t *restrict attr);
      功能:  初始化一个条件变量,创建与条件变量相关的数据信息
      参数:  cond   条件变量
              attr   属性变量,默认是在一个进程中使用 NULL
                              
      返回值:
              成功   0
              失败   错误码
              
              
  (2)int pthread_cond_signal(pthread_cond_t *cond);        
       功能:  发送一个条件给其它的线程,本身不具有有阻塞
       参数:  cond   条件变量
       返回值:
              成功    0
              失败    错误码
              
  (3)int pthread_cond_wait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex); 
       步骤:
              解锁  --  >  条件判断   -->  上锁
              
       事先要保证调用pthread_cond_wait函数的线程,进入条件判断这个位置
       功能:  等待条件满足,不满足则处于阻塞
       参数:  cond   条件变量
               mutex  互斥锁
               
       返回值:
               成功   0
               失败   错误码
               
【3】进程间通信
     (1)数据传输
     (2)信号控制
     (3)同步或者互斥
     
     七种通信方式:
     早期:  无名管道、  有名管道、   信号
     
     system  V:  
     共享内存  、  消息队列、  信号灯
               
               
     套接字通信s(不同电脑不同进程之间实现通信)          
      
     不同的进程之间要想实现数据传输只能在内核中开辟空间         
       
       
【4】管道


     是内核中的一块内存区域,区域大小是64K字节,可以实现数据的传输
     
     无名管道:在咱们当前的系统找不到对应的文件名描述管道(内存区域)
     (1)在具有亲缘关系的进程之间实现通信 
     (2)两个固定的端口,一个端口用来读数据,另外用来写数据
     (3)单向的数据传输方式,要想实现双向数据通信必须创建两个管道
     
     【注意】先去创建无名管道再去创建父子进程
     
     int pipe(int pipefd[2]);
     功能:  创建无名管道
     参数: 
          pipefd[0]   管道的读端
          pipefd[1]   管道的写端
     返回值:
          成功    0
          失败    -1
          
【5】有名管道          
     是内核中的一块内存区域,区域大小是64K字节,可以实现数据的传输
     (1)使用范围在不同的进程之间实现通信
     (2)在文件系统下,会创建一个文件,描述内存区域,具体操作通过
          操作文件描述符。
          
          
         int mkfifo(const char *pathname, mode_t mode);
         功能:  创建一个有名管道
         参数:
              pathname   在当前文件系统(当前目录)有名管道对应的文件名
              mode       对有名管道的操作权限(读和写权限)
         返回值:
              成功   0
              失败   -1
              
【6】信号


(1)信号
     是一种异步通知的方式 
     
(2)种类
     kill -l                        默认操作方式:
     2) SIGINT      ctrl+c        结束进程
     3) SIGQUIT       ctrl+\        结束进程
     9) SIGKILL                     结束进程
     
     10) SIGUSR1                    结束进程
     12) SIGUSR2                    结束进程
     13) SIGPIPE                  结束进程
     14) SIGALRM                    结束进程
     17) SIGCHLD                  忽略
     18) SIGCONT                  恢复运行  
     19) SIGSTOP                  暂停进程
     20) SIGTSTP                    暂停进程
 
 SIGKILL 和  SIGSTOP  不能改变信号的响应方式
 
(3)信号的响应方式(可以在自己的用户程序,自定义信号的处理方式)
     a、默认操作         
     b、忽略
     c、用户自定义函数处理操作(改变原有的操作方式)
     
(4)信号相关操作函数
      a、kill    raise发送信号
        int kill(pid_t pid, int sig);
        功能:  给进程发送信号
        参数:
              pid   用来指定哪一个进程  
                    正数  表示指定某一个单独的进程
                    -1    给所有的进程发送信号
                    
              sig    信号(kill -l查看)
        返回值:
              成功  0
              失败  -1
            
        int raise(int sig);
        功能: 给调用进程发送信号
        参数:
              sig   信号
        返回值:  
              成功  0
              失败  非0
              
                 
     (3) signal  信号处理函数


           sighandler_t signal(int signum, sighandler_t handler);
         功能:  信号处理函数,当一个接收到信号,执行信号处理操作
         参数:
              signum    当前用户程序要注册的信号是哪一个?
              handler   信号处理操作
                        忽略  SIG_IGN
                        默认  SIG_DFL
                        用户自定义函数  void fun(int signo)
         返回值:
              失败  SIG_ERR





DAY 06



【1】system  5  通信方式


  (1)为什么?
        
  (2)种类:共享内存   、  消息队列  、  信号量集(信号灯)


  (3)操作方式共同特点:


      key值:在系统当中让不同的进程找到内核对象


      操作标识符:让进程对内核对象进行什么样的操作
          


      命令:ipcs    查看内核对象信息
            ipcrm   删除命令 
                    -m
                    -q
                    -s


  (4)对于内核对象的操作流程
      (1)创建key值,为了内核对象和key绑定在一起,让不同的
            进程找到内核对象
      (2)创建内核对象,就已经把key和内核对象绑定在一起
      
      (3)对内核对象的操作
          共享内存:  映射和解除映射
          消息队列:  发送和接收消息
          信号量集:  申请和释放操作 
          
      (4)删除内核对象(创建好之后,一直存在,占用内存)




【2】共享内存
     (1)内黑空间中的一块区域,区域大小用户自己决定,以字节的方式
          开辟空间,可以被不同的进程访问
     (2)由于直接访问地址,在进程间通信对象中访问数据效率是最高的
     (3)注意:  不同的进程访问共享内存,可能会出现数据访问不一致
          
      a、 #include <sys/ipc.h>


       key_t ftok(const char *pathname, int proj_id);
        功能:  产生key值
        参数:
                pathname  文件的名字(必须存在可访问)   节点号  设备号
                proj_id   (1~127)  可以用ascii字符代替
        返回值:
                成功  key值
                失败  -1
                
      b、 #include <sys/shm.h>


       int shmget(key_t key, size_t size, int shmflg);
       功能:  创建内核对象(共享内存) 
       参数:
               key    通过ftok得到的整数值,用来让不同的进程找到内核对象
               size   表示用户想要创建共享内存大小是size个字节数
               shmflg 操作标志:
                      IPC_CREAT  创建内核对象
                      IPC_EXCL   防止重复创建
                      mode       9位有效权限位(0664)
       返回值:
               成功   操作标识符
               失败   -1
               
               system(“ipcs”)在程序调用shell命令执行命令的具体操作
               
               
      c、void *shmat(int shmid, const void *shmaddr, int shmflg);
        功能:  建立内核空间和用户空间的映射关系
      参数:
            shmid   操作的内核对象
            shmaddr  NULL  表示系统选择合适的内核地址空间给用户
            shmflg  
                0   表示对共享内存进行读写操作
                SHM_RDONLY表示对共享内存进行读操作
      返回值:
      
            成功   返回映射后的共享内存地址
            失败   (void*)-1  这个地方需要进行强制类型转换
            
      d、int shmdt(const void *shmaddr);
         功能:解除用户空间和内核空间的内核,不能再去操作映射后的指针变量
         参数:
             shmaddr  映射后的地址空间
             
        返回值:
              成功  0
              失败  -1


      e、int shmctl(int shmid, int cmd, struct shmid_ds *buf);
          功能:共享内存控制函数,具体控制有cmd决定
          参数:
                
                cmd操作命令
                            IPC_STAT   用来查看共享信息
                            IPC_RMID   删除共享内存


                buf   用来设置或者获取共享箱内存信息的
          返回值:
              成功    IPC_RMID  0
              失败    -1


【3】消息队列


     消息队列也是一种数据结构,用来发送消息或者接收消息,遵循先进先出的
     规则,不同点它还可以按照数据类型的方式,进行数据发送与接收
      
     int msgget(key_t key, int msgflg);
     功能:  创建一个可以按照类型发送或者接收数据的消息队列
     参数:
             key      让不同的进程找到内核对象
             msgflg   操作标志变量
                      IPC_CREAT   创建消息队列
                      IPC_EXCL    防止重复创建
                      mode        0664
    返回值:
            成功      操作标识符(非负整数)
            失败      -1


    b、int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
       功能:  发送消息
       参数:
               msgp  表示要添加消息队列里边的数据结构信息
                       struct msgbuf {
                           long mtype;       /* 数据类型message type, must be > 0 */
                           char mtext[128];    /*正文、数据 message data */
                       };
               msgsz  表示正文的大小是多少?
                      sizeof(struct msgbuf) -  sizeof(long)
               msgflg 操作标志
                      0          表示已阻塞的方式发送或者接收数据
                      IPC_NOWAIT 表示非阻塞的方式发送或者接收数据
      返回值:
              成功     0
              
              失败     -1


      c、ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                      int msgflg);
      功能: 从消息队列中接收某种类型的数据
      参数:
               msgp  表示要添加消息队列里边的数据结构信息
                       struct msgbuf {
                           long mtype;       /* 数据类型message type, must be > 0 */
                           char mtext[128];    /*正文、数据 message data */
                       };
               msgsz  表示正文的大小是多少?
                      sizeof(struct msgbuf) -  sizeof(long)
               msgflg 操作标志
                      0          表示已阻塞的方式发送或者接收数据
                      IPC_NOWAIT 表示非阻塞的方式发送或者接收数据
              msgtyp 消息类型
       返回值:
               成功  返回从正文读取的字节数
               失败  -1


       c、int msgctl(int msqid, int cmd, struct msqid_ds *buf);
       功能:消息队列控制函数
       参数:
              cmd  操作命令
                    IPC_STAT   获取消息队列相关的数值
                    IPC_RMID   删除一个消息队列,唤醒所有等待的进程
              buf  存放消息队列信息的指针变量
              
       返回值:
              IPC_RMID
              成功   0
              失败   -1


【4】信号量集(信号灯)
     目的:  用来实现进程之间访问共享资源,达到实现同步或者是互斥的目的
            来保护共享资源,来保证一个完整性的操作。
            
            
     申请操作
         a、假如信号量这个资源的数量为0,当前这个进程处于阻塞
         b、假如信号量资源的数量大于0, 从申请位置继续往下运行
     
     
     释放操作       
         a、假如信号量这个资源的数量为0 ,有进程申请资源,阻塞的进程申请
         到资源继续往下运行。
          


    (1)int semget(key_t key, int nsems, int semflg);
          功能:  创建一个信号量集合
          参数:
                  nsems   集合中信号量的个数是多少?
                  semflg  操作标志
                          IPC_CREAT   创建信号量集合
                          IPC_EXCL    防止重复创建
                          mode        0664
         返回值:
                  成功  非负整数
                  失败  -1
                  
    (2)int semctl(int semid, int semnum, int cmd, ...);
         功能:  信号量的控制操作(初始化、删除操作)
         参数:
                 semnum  表示第几个信号量,从0开始
                 cmd     对信号量的操作是什么?
                 第四个参数有cmd中命令决定,具体查看手册中共用体成员解释
             
         返回值:
                 成功   0(SETVAL)
                 失败   -1
    (3)int semop(int semid, struct sembuf *sops, unsigned nsops);
          功能:信号量的操作函数
          参数:
                sops  表示对信号量的操作方式是什么?
                      struct  sembuf
                      {
                         unsigned short sem_num;  /* semaphore number 哪一个信号量*/
                         short          sem_op;   /* semaphore operation   申请释放操作*/
                                                  正数  释放操作 、  负数  申请操作
                         short          sem_flg;  /* IPC_NOWAIT非阻塞方式、  0阻塞方式*                               
                      }


          返回值:
                成功  0
                失败  -1





























































              
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
              
              
              
              
              
              
              
    
    
    
    
    
    
    




















                   
                    















































































































  











































































































































































































































































































 
       
       
       
          
          
          




























































































  
    
    
    
    
    
    



















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值