复习一下(7.19)

一、dup、dup2

int dup(int oldfd);

int dup2(int oldfd,int newfd);

dup函数创建一个新的文件描述符,该新文件描述符和原文件描述符指向相同的文件、管道或者网络连接,并且dup返回的新文件描述符是取系统当前可用的最小整数值,dup2和dup类似,不过它返回的是第一个不小于新文件描述符的整数值,dup和dup2调用失败时都返回-1并设置errno

二、stdin、stdout、stderr和STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO的区别和联系

stdin类型为 FILE*
STDIN_FILENO类型为 int

三、浅谈printf、fprintf、sprintf的使用和区别

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

fprintf可以把数据写入文件中,借助的是第一个参数(FILE*的指针)

fprintf比printf也只多了一个FILE*指针,后面两个参数和printf一样写就行

sprintf的作用:
官方点: sprintf的作用是将一个格式化的字符串输出到一个目的字符串
参数里的buffer指针就是指向目的字符串的
简单点:把数据输出到一个字符串

四、Linux access函数讲解

#include<unistd.h>

int access(const char* pathname, int mode);

参数介绍:

    pathname 是文件的路径名+文件名

    mode:指定access的作用,取值如下

F_OK 值为0,判断文件是否存在
 
X_OK 值为1,判断对文件是可执行权限
 
W_OK 值为2,判断对文件是否有写权限
 
R_OK 值为4,判断对文件是否有读权限
 
注:后三种可以使用或“|”的方式,一起使用,如W_OK|R_OK

五、C语言strlen与sizeof的区别详解

strlen 是一个函数,它用来计算指定字符串 str 的长度,但不包括结束字符(即 null 字符)。

六、进程

1、fork()创建进程、复制地址空间

子进程返回0,父进程返回子进程pid

2、sleep()进程挂起

3、wait()、waitpid()进程收尸、等待进程

4、exit()、_exit()进程结束

5、exit库函数、_exit函数系统调用

exec族进程替换、完全替换、进程号不变

               int execl(const char *path, const char *arg, ...  /* (char  *) NULL */);
               int execlp(const char *file, const char *arg, .../* (char  *) NULL */);
               int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const envp[] */);
               int execv(const char *path, char *const argv[]);
               int execvp(const char *file, char *const argv[]);
               int execvpe(const char *file, char *const argv[],char *const envp[]);
                解析:
                    1>exec函数族一共有6个成员 
                    2>exec函数族都是exec开头
                    
                    不带p :根据路径来加载程序
                    带p   :根据(执行目录)文件名来加载程序 默认路径:/usr/bin     和 /bin 用来保存命令            
                    带l      :根据列举来加载程序    --->直接提供参数 
                    带v   :根据数组来加载程序     --->将参数塞入到数组中,并以数组作为参数给函数
                    带e   :根据环境变量加载程序后传递某些数据
                    
                exec失败返回-1,并设置错误码

七、进程通信

1、有名管道

mkfifo("./fifo",0777)创建有名管道

2、无名管道

只适用于父子进程

char pp[1];

pipe(pp)创建无名管道

3、信号

唯一异步通信,类似中断。

raise()发信号给自身进程

alarm()闹钟

kill()发信号

pause()等待信号

signal()注册信号

4、消息队列

ipcs  -q

ipcrm -q  <id>

   int msgget(key_t key, int msgflg);   //创建或获取消息队列
    //参数1 ---- 消息队列的key:
                方法一:IPC_PRIVATE  ---- 系统自动分配key
                方法二:调用函数ftok ---返回key值
                key_t ftok(const char *pathname, int proj_id);
                //参数1 ---- 字符串,表示工程路径
                //参数2 ---- 工程编号
                //返回值----成功:key,失败:-1
    //参数2 ----- 消息队列的权限,一般为: IPC_CREAT | 0666
   IPC_CREAT    如果key不存在,则创建(类似open函数的O_CREAT)
   IPC_EXCL       如果key存在,则返回失败(类似open函数的O_EXCL)
   IPC_NOWAIT  如果需要等待,则直接返回错误
    //返回值 ---- 成功:消息队列的ID,失败:-1

   int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    //参数1 ----- 消息队列ID
    //参数2 ----- 结构体struct msgbuf 类型的指针 ,,该结构体需要自定义
                  struct msgbuf {
                       long mtype;       /* message type, must be > 0 */  消息类型
                       char mtext[1];    /* message data */   消息正文
                   };
    //参数3 ----- 消息正文的实际字符长度
    //参数4 ----- 发送方式:
                    IPC_NOWAIT  消息没有发送完成函数也会立即返回。
                    0:直到发送完成函数才返回
      //返回值 ------ 成功:0,失败:-1

    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
    //参数1 ----- 消息队列ID
    //参数2 ----- 结构体struct msgbuf 类型的指针 ,,该结构体需要自定义
                  struct msgbuf {
                       long mtype;       /* message type, must be > 0 */  消息类型
                       char mtext[1];    /* message data */   消息正文
                   };
    //参数3 ----- 消息正文的长度
    //参数4 ----- 要接收的消息的类型msgtyp
                     msgtyp = 0,表示接收消息队列中第一个消息(按顺序接收所有类型消息)
                     msgtyp > 0,表示接收指定类型的消息
                     msgtyp < 0,表示接收消息类型不大于msgtyp的绝对值的最小消息
    //参数5 ----- 发送方式:
                    IPC_NOWAIT  消息没有发送完成函数也会立即返回。
                    0:直到发送完成函数才返回
      //返回值 ------ 成功:接收的消息的字节数,失败:-1

    int msgctl(int msqid, int cmd, struct msqid_ds *buf);
    //参数1 ---- 消息队列ID
    //参数2 ---- 命令:cmd
                    IPC_STAT ---- 获取消息队列属性
                    IPC_SET  ---- 设置消息队列属性
                    IPC_RMID ---- 删除消息队列
    //参数2 ---- 如果mcd不是IPC_RMID,则需要该参数,struct msqid_ds结构体指针
                struct msqid_ds {
                   struct ipc_perm msg_perm;     /* Ownership and permissions */
                   time_t          msg_stime;    /* Time of last msgsnd(2) */
                   time_t          msg_rtime;    /* Time of last msgrcv(2) */
                   time_t          msg_ctime;    /* Time of last change */
                   unsigned long   __msg_cbytes; /* Current number of bytes in
                                                    queue (nonstandard) */
                   msgqnum_t       msg_qnum;     /* Current number of messages
                                                    in queue */
                   msglen_t        msg_qbytes;   /* Maximum number of bytes
                                                    allowed in queue */
                   pid_t           msg_lspid;    /* PID of last msgsnd(2) */
                   pid_t           msg_lrpid;    /* PID of last msgrcv(2) */
               };
    //返回值 ---成功:0,失败:-1

5、共享内存

ipcs -m

  int shmget(key_t key, size_t size, int shmflg);
    //参数1 ---- 共享内存的key:
                方法一:IPC_PRIVATE  ---- 系统自动分配key
                方法二:调用函数ftok ---返回key值
                key_t ftok(const char *pathname, int proj_id);
                //参数1 ---- 字符串,表示工程路径
                //参数2 ---- 工程编号
                //返回值----成功:key,失败:-1
    //参数2 ----- 共享内存的大小
    //参数3 ----- 共享内存的权限,一般为: IPC_CREAT | 0666
    //返回值 ---- 成功:共享内存的ID,失败:-1

    void *shmat(int shmid, const void *shmaddr, int shmflg);
    //参数1 ---- 共享内存id
    //参数2 ---- 指定映射虚拟空间地址,但是,一般为NULL,由系统自动映射
    //参数3 ---- 共享内存使用权限
                    SHM_RDONLY:共享内存只读
                    默认0:共享内存可读写
    //返回值 -----成功:映射的虚拟空间地址,失败:-1

   int shmdt(const void *shmaddr);
    //参数 ------映射的进程的虚拟地址,也就是shmat()返回的地址
    //返回值 ----- 成功:0,失败:-1

    int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    //参数1 ---- 共享内存ID
    //参数2 ---- 命令:cmd
                    IPC_STAT ---- 获取共享内存属性
                    IPC_SET  ---- 设置共享内存属性
                    IPC_RMID ---- 删除共享内存
    //参数2 ---- 如果mcd不是IPC_RMID,则需要该参数,struct msqid_ds结构体指针
                struct shmid_ds {
                   struct ipc_perm shm_perm;    /* Ownership and permissions */
                   size_t          shm_segsz;   /* Size of segment (bytes) */
                   time_t          shm_atime;   /* Last attach time */
                   time_t          shm_dtime;   /* Last detach time */
                   time_t          shm_ctime;   /* Last change time */
                   pid_t           shm_cpid;    /* PID of creator */
                   pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */
                   shmatt_t        shm_nattch;  /* No. of current attaches */
                   ...
               };

    //返回值 ---成功:0,失败:-1

6、信号量

信号灯(semaphore),也叫信号量。它是不同进程间或一个给定进程内部不同线程间同步的机制

信号灯种类:
    posix有名信号灯
    posix基于内存的信号灯(无名信号灯)
    System V信号灯(IPC对象)
从使用上分为二值信号灯和计数信号灯两种:

1》 二值信号灯 -----表示资源是否可用
    值为0或1。与互斥锁类似,资源可用时值为1,不可用时值为0。
2》计数信号灯 -----表示资源数量
    值在0到n之间。用来统计资源,其值代表可用资源数

用信号灯实现进程的同步,需要实现两个操作
3》等待操作
    等待操作也叫P操作,等待信号灯的值变为大于0,然后将其减1;
4》释放操作
    释放操作也叫V操作,用来唤醒等待资源的进程或者线程
5》System V的信号灯
    是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。

    int semget(key_t key, int nsems, int semflg);
    //参数1 ---- 信号灯的key:
                方法一:IPC_PRIVATE  ---- 系统自动分配key
                方法二:调用函数ftok ---返回key值
                key_t ftok(const char *pathname, int proj_id);
                //参数1 ---- 字符串,表示工程路径
                //参数2 ---- 工程编号
                //返回值----成功:key,失败:-1
    //参数2 ----- 信号灯对象(集合)中的信号灯的个数
    //参数3 ----- 信号灯的权限,一般为: IPC_CREAT | 0666
    //返回值 ---- 成功:信号灯的ID,失败:-1

    int semop(int semid, struct sembuf *sops, size_t nsops);
    //参数1 ----- 信号灯对象的ID
    //参数2 ----- 结构体struct sembuf的指针
                struct sembuf {
                        unsigned short  sem_num;        /* semaphore index in array 操作的信号灯的下标 */
                        short           sem_op;         /* semaphore operation 
                                                        0 :  等待,直到信号灯的值变成0
                                                          1  :  释放资源,V操作
                                                        -1 :  分配资源,P操作*/
                        short           sem_flg;        /* operation flags:0,  IPC_NOWAIT,  SEM_UNDO */
                };
    //参数3 ----要操作次数
    //返回值 -----成功:0,失败:-1

    int semctl(int semid, int semnum, int cmd, ...);
    //参数1 ---- 信号灯对象ID
    //参数2 ---- 要操作的信号灯的编号
    //参数3 ---- 名称cmd:
                GETVAL:获取一个信号灯的值
                SETVAL:设置一个信号灯的值
                IPC_RMID:从系统中删除信号灯集合
                GETALL:获取所有信号灯的值
                SETALL:设置所有信号灯的值
   //参数4 ----- 联合体,该联合体需要自定义,如下:
                   union semun {
                   int              val;    /* Value for SETVAL  设置一个信号灯的值时使用 */
                   struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
                   unsigned short  *array;  /* Array for GETALL, SETALL 获取或设置所有信号灯的值时使用 */
                   struct seminfo  *__buf;  /* Buffer for IPC_INFO    (Linux-specific) */                  
                };

八、线程

    int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);   创建线程
    Compile and link with -pthread.    -------//如果程序中使用上面函数,编译时,需要链接库: -lpthread
    
    //参数1 ---- 保存线程ID的变量地址
    //参数2 ---- 线程属性,一般为NULL,默认属性
    //参数3 -----线程执行的函数(线程函数),格式必须为:
                    void* 线程函数名称(void * arg)    
                    {
                        //线程执行代码
                        ........
                    }
    //参数4 ---- 传给线程的参数
    //返回值 ----成功:0,失败:非0值

  void pthread_exit(void *retval);   结束线程  //Compile and link with -pthread.
    //参数 -----线程返回的数据地址,该数据必须在线程返回后空间没有释放

  #include <pthread.h>
    int pthread_join(pthread_t thread, void **retval);  线程收尸 // Compile and link with -pthread.
    //参数1 ----线程ID
    //参数2 ---- 保存线程返回值的指针的地址
    //返回值 --- 成功:0,失败:非0

    int pthread_cancel(pthread_t thread);    //Compile and link with -pthread
    //参数 ---- 线程ID
    //返回值 ---- 成功:0,失败:非0

1》概念
    在创建线程时,默认为结合属性,当线程结束时,它不会自动释放资源,需要主线程调用pthread_join()来回收资源
    在创建线程时,也可以将线程的属性改为分离属性,此时,当线性结束时,会自动释放资源,此时不需要再调用pthread_join()
设置线程的分离属性有两种方式:
2》方式一:直接给pthread_create传递线程属性变量,设置分离属性
    int pthread_attr_init(pthread_attr_t *attr);  //初始化线程属性变量
    int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
    //参数1 ---- 属性变量地址
    //参数2 ---- 要设置的属性:
                    PTHREAD_CREATE_DETACHED   ---分离
                    PTHREAD_CREATE_JOINABLE   ---结合

3》使用线程函数
    int pthread_detach(pthread_t thread);
    //参数 ---- 线程ID
    //返回值 ---- 成功:0,失败:非0
    

pthread_t pthread_self(void);
//返回调用该函数的线程的ID

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值