APUE学习笔记(部分)

APUE学习笔记(部分)

在这里插入图片描述
Xmind格式文件自取

第一章 Unix基础知识

操作系统的体系结构

输入输出

头文件<unistd.h>

  • 每当运行一个新程序时,所有的shell 都为其打开3 个文件描述符,即标准输入(standard input )、标准输出( standard output ) 以及标准错误(standard error )
  • open read write lseek close提供了不带缓冲的IO
  • 两个常量STDIN_FILENO和STDOUT_FILENO指定了标准输入输出的文件描述符。STDERR_FILENO定义了标准错误的描述符

系统调用与库函数

  • C库函数与系统调用的差别
  • 系统调用通常提供一种最小接口 , 而库函数通常提供比较复杂的功能 。

第二章 Unix标准及实现

标准及限制略

选项

头文件<unistd.h>

  • 与文件或目录无关的运行时选项用 sysconf 函数来判断
  • 文件或目录有关的运行时选项通过调用pathconf 或 fpathconf 函数来判断

基本数据类型

头文件<sys/type.h>

  • 一些常用的基本数据类型

第三章 文件IO

对于内核而言,所有打开的文件都通过文件描述符引用,当打开或创建一个文件是,内核都向进程返回一个文件描述符。标准输入输出描述符如:

open与opennat

头文件<fcntl.h>

  • 打开或创建一个文件
  • oflag参数(读写):
    下列参数必须且只可指定一个
    O_RDONLY 只读打开
    O_WRONLY 只写打开
    O_RDWR 读、写打开
    O_EXEC 只执行打开
    O_SEARCH 只搜索打开
  • oflag参数(可选)
    O_APPEND 每次写追加到文件的尾端
    O_CLOEXEC 把FD_CLOEXEC常量值设置为文件描述符标志
    O_CREAT 文件不存在则创建它,新创建的文件访问权限位由mode参数指定
    O_EXCL 若文件已存在,则出错
    O_NOCTTY 不讲path引用的终端设备作为进程的控制终端
    O_DIRECTORY path不是目录则出错
    O_NOFOLLOW NO符号链接
    O_NOBLOCK 非阻塞方式
    O_TRUNC 文件存在则文件长度截断为0

文件操作函数

头文件<unistd.h>

  • int creat (const char *path, mode_t mode);
    等效于
    int open (const char *path, O_WRONLY|O_CREAT_O_TRUNC, mode_t mode);
  • int close (int fd)
  • off_t lseek (int fd, off_t offset, int whence);
    whence:
    SEEK_SET 开始处设置
    SEEK_CUR 当前位置设置
    SEEK_END 文件结束位置设置
  • write read
    fd, *buf, size
    返回操作的字数

文件共享

函数dup和dup2
头文件<unistd.h>

  • 函数返回的新文件描述符与参数fd共享同一个文件表项。

函数fcntl

头文件<fcntl.h>

  • 形式:
    int fcntl ( int fd, int cmd, … /* int arg */ );
  • 功能:

函数 ioctl

头文件<unistd.h>
<sys/ioctl.h>

  • 形式:
    int ioctl (int fd, int request, … );

第四章 文件与目录

函数stat、fstat、fstatat和lstat

头文件:<sys/stat.h>

  • 返回文件的stat信息
  • struct stat {

文件类型

头文件:<sys/stat.h>

  • 以stat中mode判断的文件类型
  • 以结构体指针判断的文件类型

文件系统

目录读取

头文件:<dirent.h>

  • readdir(DIR *dp),每次用目录中取出一项直到返回值为NULL
  • dirent结构与实现有关,实现此结构的定义至少包括下列两个成员
    ino_t d_ino // i节点
    char d_name[]; // 文件名

第五章 标准IO库

标准输入,标准输出和标准错误

第六章 系统数据文件与信息

口令文件

头文件<pwd.h>

  • /etc/passwd文件中的字段
  • POSIX.1定义了获取口令文件项的函数
    struct passwd* getpwuid(uid_t uid) //通过uid
    struct passwd *getpwnam(const char *name) //通过登录名

阴影文件

头文件<shadow.h>

  • /etc/shadow文件中的字段
  • 错误返回NULL

组文件

头文件<grp.h>

  • 具体函数形式同上

时间和日期例程序

头文件<time.h> <sys/time.h>

  • 支持通过参数格式化产生的字符串
  • 字符串转时间
  • 时间日期格式化标识符

第七章 进程环境

进程终止

头文件<stdlib.h> <unistd.h>

  • <stdlib.h>
    void exit (int status);
    void _Exit(int status);

<unistd.h>
void _exit(int status);
_exit 和 _Exit立即进入内核
exit先执行一些清理处理,然后返回内核

  • <stdlib.h>
    int atexit (void (*func)(void))
    登记退出处理程序,exit调用这些函数从顺序与它们登记时候的顺序相反
  • C程序的启动和终止

储存空间布局

储存空间分配

头文件<stdlib.h>

函数 setjmp和longjump

头文件<setjmp.h>

  • env的类型是一个特殊类型,通常将其设定为全局变量
  • 当longjmp返回到main函数所示,变量的值恢复情况变化是不确定的

函数getrlimit和setrlimit

头文件<sys/resource.h>

  • 成功返回0,失败非0
  • 对应rlimit结构

第八章 进程控制

函数fork

头文件<unistd.h>

  • pid_t fork(void)
    子进程返回0,父进程返回子进程ID(大于0),若出错,返回-1
    子进程获得父进程数据空间、堆和栈的副本(不共享)
  • 文件共享
    子进程与父进程共享一个文件表项,也就是说,子进程与父进程的读写偏移量保持一致
  • 要使其保持不一致可以先用dup2函数获得一个指向同一个流的fd

函数vfork

头文件<unistd.h>

  • 与fork不同的地方:
    1.子进程在父进程的空间内运行
    2.保证子进程先运行,在子进程调用exec或exit之间父进程都被阻塞。调用之后父进程恢复运行。

函数exit

头文件<stdlib.h><unistd.h>

  • 进程的最后一个线程return返回值不作为进程的返回值,改终止状态为0
  • 三种异常终止:
    abort 产生SIGABRT信号
    进程接收到某些信号且信号的处理程序为结束改进程
    最后一个线程对“取消”请求作出响应

函数wait和waitpid

头文件<sys/wait.h>

  • #include <sys/wait.h>
    pid_t wait (int *statloc);
    pid_t waitpid(pid_t pid, int *statloc, int option)
    成功返回0,出错返回0或者1
  • option常量
  • waitid函数提供了更多的灵活性,可以指定等待子进程的限制
    #include <sys/wait.h>
    int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);

函数exec

头文件<unistd,h>

  • 7个exec函数之间的关系

解释器文件

头文件<unistd.h>

  • 解释器文件是文本文件,其起始行的形式是:
    #! pathname [optional-arguments]
    pathname指向解释器
  • 注意用execl执行时,第一个参数应该为执行文件名

函数system

头文件<stdlib.h>

  • 函数形式
    int system(const char *cmdstring)

第九章 进程关系

终端登录与网络登录

  • 终端登录
  • 完成login之后的进程安排
  • 网络登录
  • 网络登录后的进程安排

进程组与会话

头文件<unistd.h>

  • int setpid(pid_t pid, pid_t pgid);
    一个进程只能为他自己或他的子进程设置进程组id,当它的子进程调用exec后,不能再更改它的组id
  • 会话是一个或多个进程组的集合
  • 进程调用setsid建立一个新会话
    pid_t setsid(void)
    如果该进程不是进程组的组长,则他会创建一个新会话,并变成会话首进程。

控制终端

  • 如果一个会话有一个控制终端,则它有一个前台进程组,其他进程组为后台进程组 。
    键入终端的中断键或者退出键,都会讲信号发送至前台进程组的所有进程。

作业控制

第十章 信号

信号概念

  • Unix系统信号
  • SIGCHLD信号:子进程终止或停止时,SIGCHLD被送给其父进程
    SIGUSR1和SIGUSR2为用户定义的信号,可用于应用程序

函数signal

头文件<signal.h>

  • 函数形式
    void (*signal(int signo, void (*func)(int)))(int);
    成功返回一千的信号处理配置,出错则返回SIG_ERR
  • exec 函数将原先设置为要捕捉的信号都更改为默认动作,其他信号的状态则不变(一个进程原先要捕捉的信号,当其执行一个新程序后,就不能再捕捉了,因为信号捕捉函数的地址很可能在所执行的新程序文件中已无意义)。

可重入函数

  • 可重入函数

函数kill和raise

函数pause和alarm
头文件<signal.h>

  • 函数形式
    int kill(pid_t pid, int signo);
    int raise(int signo);
  • pid值根据不同值有不同含义

0 发送至指定进程组
=0 发送至同一进程组的所有进程
<0 发送至进程组id为-pid的所有进程(要有权限)

  • int pause(void)
    只有执行了一个信号处理程序并返回,pause才返回,返回值为-1
  • unsigned int alarm(unsigned int seconds);
    经过second产生SIGALARM信号,其默认处理是终止进程

信号集

头文件<signal.h>

  • 五个处理信号集的函数,各函数功能从函数名称可推断出
  • 函数sisprocmask
    int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset)
    how参数功能如下
  • 函数sigpending
    int sigpending(sigset_t *set);
    返回当前未决的信号

函数sigaction

函数sigsetjmp和siglongjmp
函数sigsuspend
头文件<signal.h>

  • 函数形式
    int sigaction(int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);
    以一个信号处理结构简化了屏壁值设定以及替代了早期的signal函数
  • 与setjmp唯一区别是带了mask参数,使得跳转的时候能恢复保存的信号屏蔽字
  • 恢复信号屏蔽字然后进程休眠等待信号操作(原子操作以防信号丢失)
    int sigsuspend(const sigset_t *sigmask);
    返回值-1并将errno设置为EINTR

作业控制信号

  • SIGCHLD 子进程已停止或终止。
    SIGCONT 如果进程已停止,则使其继续运行。
    SIGSTOP 停止信号(不能被捕捉或忽略)。
    SIGTSTP 交互式停止信号。
    SIGTTIN 后台进程组成员读控制终端。
    SIGTTOU 后台进程组成员写控制终端。

第十一章 线程

线程创建与终止

头文件<pthread.h>

  • 线程id只在当前进程上下文中才有意义,其数据类型为pthread_t,不能作为整数处理进行比较操作。int pthread-euqal( )进行比较操作。当前线程打印其线程id
    pthread_t pthread_self(void);
  • 线程创建:
    int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void (start_rtn) (void), void *restrict arg);
    其中:
    tidp: 线程id所处的内存单元
    attr:一系列线程属性
    startrtn:线程开始运行的函数地址,只有一个无类型指针参数
    arg:函数开始地址的函数参数补充
  • 线程终止:
    线程有三种推出方式:
  1. 简单的从启动例程中返回,返回值为线程的退出码。
  2. 可以被同一进程的其他线程所取消。
  3. 线程调用pthread_exit退出
  • void pthread_exit(void *rval_ptr);
    其他进程访问rval_ptr(返回状态内存单元?)
    int pthread_join(pthread_t thread, void **rval_ptr);

进程同步

头文件<pthread.h>

  • 互斥量创建与销毁:
    int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
    int pthread_mutex_destroy(pthread_mutex_t *mutex);
    mutex即初始化的锁, attr为其相关属性
  • 如果线程不希望被阻塞,它可以使用 pthread_mutex_trylock 尝试对互斥量进行加锁。如果调用 pthread ute _trylock 时互斥蜇处于未锁住状态,那么 pthread_mutex trylock将锁住互斥械,不会出现阻塞直接返回 0, 否则 pthread mutex_trylock 就会失败,不能锁住互斥量,返回 EBUSY
  • 读写锁:
    形式上与互斥量类似,但是并行度要更高
    lock-> rlock wlock
  • 条件变量:
    等待的参数为一个条件变量,条件变量本身是受互斥量保护的。
    lock -> cond
  • 自旋锁:
    与互斥量类似,但是不是通过互斥量类似的休眠机制。而是在获取锁之前一直处于忙等状态。适用于只持有锁一小段时间且不想进程调用所带来开销的场景:
    非抢占式内核非常有用,但是在用户层效率一般(时间片机制阻塞)
    lock -> spin
  • 屏障:等待直到所有进程都达到某一点, count规定达到的线程数量

第十二章 线程控制

线程属性

头文件 <pthread.h>

  • init函数可以修改线程属性默认值
  • 如果线程不需要了解线程的终止属性,可以修改pthread_attr_t结构中的 detachstate属性,可以设置为PTHREAD_CREATE_DETACHED和PTHREAD_CREATE_JIONABLE。下面函数可以获取、修改当前线程detachstate线程属性

同步属性

头文件 <pthread.h>

  • 类似于线程属性,同步属性可以用init函数进行默认同步属性的初始化和反初始化 attr-> mutexattr
  • 同步属性中四个重要的属性值:(都相应的可以用pthread_mutexattr_get***)进行获得和修改:
    1:共享属性 get(set)pshared 如果设置为PTHREAD_PROCESS_SHARED,从多个线程共享的内存数据块中的互斥量(读写锁/条件变量/屏障)就可以用于这些线程的同步。
    2:健壮性属性 get(set)robust 处理但一个持有互斥量的线程终止导致其他线程长时间阻塞的问题。终止时并没有对该锁进行解锁,此时线程会阻塞,pthread_mutex_lock 返回的值为 EO ERDEAD 而不是0. 线程可以调用pthread_mutex_consistent(pthread_mutex_t *mutex);使得互斥量恢复可用,并指明线程状态与解锁前是一致的。
    3:时钟属性 get(set)lock : 规定pthread_cond_timedwait所采用的是哪个时钟
    4:类型属性 settype 定义了一些加锁和解锁的一些限制:

线程特定(私有数据)数据

  • 在分配特定数据之前,需要创建与该数据关联的键,键用于获取对线程特定数据的访问
  • 键一旦创建以后,就可以通过调用 thread_setspecific 函数把键和线程特定数据关联起来。可以通过 pthread getspecific 函数获得线程特定数据的地址:

线程与信号/fork/IO

头文件:<pthread.h> <unistd.h>

  • 每个线程都有自己的信号屏蔽字,但是对于信号的处理是所有线程共享的,线程的屏蔽字设置函数如下:
  • 向单个线程发送信号:
    int pthread_kill (pthread_t thread, int signo);
  • 在子进程 只存在 个线程,它是由父进程中调用 fork 的线程的副本构成的 如果父进程中的线程占有锁,子进程将同样占有这些锁 问题是子进程并不包含占有锁的线程的副本,所以子进程没有办法知道它占有了哪些锁、需要释放哪些锁.清除锁状态的函数:

int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void) );

prepare fork处理函数由父进程在fork创建子进程之前调用,任务是获取父进程定义的锁。parent fork为fork创建子进程之后,返回上下文之前在父进程调用的,任务是对prepare fork确定的所有锁进行解锁。child fork是返回子进程上下文之前在子进程调用的,任务与parent一致。

  • pread pwrite为原子操作,可以解决并发线程对同一文件进行读写的一致性问题

第十三章 守护进程

守护进程的特征

  • 守护进程(daemon)是没有控制终端,在后台运行,仅在系统关闭时才终止的进程,Unix系统有很多守护进程,执行日常事务

编程规则

头文件 <stdlib.h> <unistd.h>

  • 1:调用umask将文件模式设置为一个已知值
    2:调用fork,然后使父进程exit。目的是确保进程不是一个进程组的组长进程。
    3:调用setsid创建一个新会话,然后此进程成为新会话的首进程,成为一个新进程组的组长进程,同时没有控制终端。
    4:将当前工作目录更改为根目录。
    5:关闭不需要的文件描述符。
    6:将文件描述符 0、1、2由原来的标准输入 输出 更改为/dev/null 使其输入输出错误均与终端无关

出错记录

头文件 <syslog.h>

  • syslog:一个集中守护进程出错记录措施
    上图分别对于三种产生日志消息的方法。
    1:调用syslog(3) 函数产生日志消息,使得该消息发送至Unix域数据报套接字 /dev/log
    2:将日志消息发送至UDP端口514.
    3:内核例程调用log函数。
  • syslogd读取所有三种格式的日志消息。该守护进程启动时会读取/etc/syslog.conf以确定不同种类的消息该送往何处。syslog函数如下:
    openlog函数中,可以指定一个ident,通常是程序的名称。此名称将加至每则日志消息中;option定义了一些选项说明。

守护进程惯例

  • 1:若守护进程使用锁文件,那么改文件一般储存与/var/run中,守护进程需有root权限才能彩瓷目录创建文件
    2:若守护进程支持配置选项,那么配置文件通常存放在/etc文件夹中,其配置文件名字通常是name.conf
    3:守护进程通常是由系统初始化脚本进行启动的(/etc/rc或/etc/init.d/)
    4:如果一个守护进程有一个配置文件,那么该进程一般会在进程启动时读取,中途变更配置文件守护进程不能及时进行更改。

第十四章 高级IO

fcntl纪录锁

头文件 <fcntl.h>

  • fcntl纪录锁原型:
    int fcntl (int fd, int cmd, …/* struct flock * flockptr */);

其中 fd为文件标识符, cmd为F_GETLK、F_SETLK、或F_SETLKW,第三个参数为指向一个flock参数的指针

  • flock结构及类成员说明:
    type:所希望的锁类型,共享读、独占性或解锁一个区域
    whence:解锁区域字节偏移量 start:加锁区域字节偏移量
    len:区域字节长度 l_pid:pid为该值的持有的锁能阻塞当前进程
  • fcntl三种命令:
    F_GETLK:判断有flockptr所描述的锁是否会被排斥,若是,则阻止创建flockptr所描述的锁,并将改锁的信息重写flockptr;如果不是,则将flockptr所描述的锁l_type设置为F_UNLCK
    F_SETLK:设置锁,若系统阻止,函数立即范围,errno设置为EACCES或EAGAIN
    F_SETLKW:FSETLK的阻塞版本,系统阻止后该调用进程休眠,知道创建的锁可用进程被唤醒
  • 继承关系
    1:纪录锁与文件相关,当一个文件关闭,任何指向该文件的文件描述符都会失效
    2:子进程不会继承父进程所获得的锁
  • 建议性锁和强制性锁
    建议性锁一般用在合作进程。并且没有其他方式对文件进行读写时使用,内核在加锁之后不会负责检查。(性能好)
    强制性锁会让内核检查每一个open、read和、write以验证调用进程是否违背了正在访问该文件的某一把锁

I/O多路转接

头文件 <sys/select.h> <poll.h>

  • 函数select
    maxfdp1是描述符集中最大描述符, readfds writefds exceptfds分别对于 读 写 和 异常描述符集, tvptr为0时函数不等待直接返回, tvptr不为0时,当指定描述符之一或等待超过指定的时间是返回, 为NULL时则永远等待直到捕捉到一个指定的可用信号
  • 函数poll
    poll不是为每个条件构造一个描述符集,而是构造一个pollfd结构数组:
    struct pollfd {
    int fd;
    short events;
    short reventsl
    } ;

异步I/O

头文件 <signal.h>

  • select和poll可以实现异步形式的通知,而信号机构提供了一种异步形式通知某种时间已发送

  • System V异步I/O:
    STREAMS系统的一部分,需要调用ioctl并将其第二个参数(request)设置为I_SETSIG,指定SIGPOLL信号的条件,并且在调用ioctl之前建立信号处理程序

  • BSD异步I/O:
    BSD派生系统中,SIGIO是通用异步信号,SIGURG用来通知网络连接带外数据到达

  • POSIX异步I/O
    POSIX为不用类型的文件进行异步I/O提供了一套一致的方法
    头文件 <aio.h>

    • 异步I/O接口使用AIO控制块来描述I/O操作
      aio_filedes为打开用来读或写的文件描述符
      _offset指定读或写的偏移量
      _buf为读入后存放或写入来源的缓冲区
      _nbytes为_buf缓冲区大小
      _reqprio为请求提示顺序
      _sigevent为字段控制,描述I/O时间结束后如何提示应用程序
    • sigevent结构:
      _notify:SIGEV_NONE,完成后不通知进程;SIGEV_SIGNAL,I/O完成后,由_signo指定的信号来通知应用程序;SIGEV_THREAD,I/O操作完成时,将调用_function,属性由_attributes指定,默认该函数将在分离状态下的一个单独线程中运行
    • 相关函数
      读写操作:
      int aioread(struct aiocb *aiocb);
      int aiowrite(struct aiocb *aiocb);
      设置同步:
      int aio_fsync(int op struct aiocb *aiocb);
      获取完成情况:0 完成
      int aio_error(const struct aiocb *aiocb);
      阻塞进程知道所有异步I/O完成:
      int aio_suspend(const struct aiocb *const list[], int nent, const struct timespec *timeout)

储存映射I/O

头文件 <sys/mman.h>

  • 功能:存储映射 ( memory-mapped )能将一个磁盘文件映射到存储空间中的某个缓冲区上。于是,当从缓冲区中取数据时,就相当于读文件中的相应字节。可以在不适用write和read的条件下执行I/O
  • mmap函数
    void *mmap(void *addr, size_t len. int prot, int flag, int fd, off_t off );
    addr len为映射区的起始地址和映射长度
    prot参数指定了映射保护区的保护要求: PROT_READ 可写 PROT_WRITE PROT_EXEC可执行 PROT_NONE 不可访问
    fd为指定文件的文件描述符
    off为读取文件的偏移量,flag参数对应属性如下
    MAPFIXED 返回值必须等于addr(即最终映射的地址与函数参数传入的建议地址必须一致,若未指定,函数将传入的attr地址作为一种建议,不代表最终引用)
    MAP_SHARED / MAP_PRIVATE必须指定这两者其中一个,当程序修改映射程序时,前者指定修改映射文件而后者不影响映射文件,只对副本进行修改。
  • 更改现有映射的权限:
    int mprotect(void *addr, size_t len, int prot);
    同步映射的页与该文件:
    int msync(void *addr, size_t len, int flags);
    解除映射:
    int nunmap(void *addr, size_t len)

第十五章 进程间通信

管道

头文件 <unistd.h>

  • 创建:pipe函数
    int pipe(int fd[2]);
    fd[0]为读而打开,fd[1]为写而打开

  • 函数popen 和 pclose
    FILE *popen(const char *cmdstring, const char *type);
    int pclose(FILE *fp); 作用如下图所示

  • 协同进程:

    • 当一个过滤程序既产生某个过滤程序的输入,又读取该过滤程序的输出时,它就变成了协同进程。如下图:
    • FIFO:相较于只能用在两个相关进程的普通管道,FIFO能使两个不相关的进程也能交换数据,FIFO是一种文件类型,具体创建函数如下。

XSI IPC

头文件 <sys/ipc.h>

  • XSI IPC代表三种通信机制:消息队列,信号量与共享内存。依托标识符和键来实现:
  • 内核为每一个进程维护一个结构体形式的IPC对象,对象通过一个非负整数的IPC标识来引用
  • 若多个进程需要在同一个IPC对象上回合,则需要通过键值来引用该对象。
  • ipc_perm结构:

消息队列

头文件 <sys/msg.h>

  • 相应操作与函数:
    msgget用于用键打开或者创建一个新的id,获得消息队列标识符msqid,每一个队列都有一个msqid_ds结构与其相关联。msgctl用处获得或者修改此结构相关属性,msgsnd用于将新消息发送至队列微端,msgrcv用于从队列中取消息。
  • int msgget(key_t key, int flag); flag用于设置读写mode
    int msgctl(int msqid, int cmd, struct msqid_ds *buf); IPC_STAT/SET/RMID
    int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag);
    ssize_t msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag);
    type指定消息种类, flag值指定操作是否可阻塞。

信号量

头文件 <sys/sem.h>

  • 信号量为一个计数器,用于为多个进程提供对共享数据对象的访问

共享存储

头文件 <sys/shm.h>

  • XSI共享存储为内存的匿名段,与存储映射不同,没有显式的文件
  • int shmget (key_t key, size_t size, int flag); flag用于设置读写mode
    int shmctl(int shmid, int cmd, struct shmid_ds *buf); IPC_STAT/SET/RMID
    void *shmat(int shmid, const void *addr, int flag); 将此段连接到addr地址上
    int shmdt(const void *addr);将段与地址分离

POSIX信号量

头文件

  • 相较于SIX信号量接口,POSIX信号量接口更简单,更高性能,同时被删除时,表现更完美。POSIX信号量有命名和未命名两个版本,其中未命名版本只能用于同一进程的两个线程,而命名版本无此限制。

  • 命名版本信号量

    • sem_t *sem_open(const char *name, int oflag, … , mode_t mode, usigned int value);
      semopen用于创建或打开一个命名信号量,信号量由name指定,mode用于指定用户组群读写权限, oflag指定创建或者是打开,value设定信号量初值
    • int sem_close(sem_t *sem)
      sem_close用于释放任何信号量相关的资源
    • int sem_unlink(const char *name)
      sem_unlink用于销毁一个命名信号量
  • 非命名信号量

    • int sem_init(sem_t *sem, int pshared, unsigned int value);
      pshared非零表示在多个进程中使用该信号量,此时要确保sem指向两个进程之间共享的内存范围。
    • int sem_destroy(sem_t *sem)
  • 共有操作

    • int sem_trywait(sem_t *sem);
      int sem_wait(sem_t *sem);
      int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict tsptr);
      三者均完成信号量的减一操作,trywait在信号量为0时立即返回-1并将errno置为EAGAIN, wait在信号量为0时发生阻塞,直到成功使信号量减一,第三个则在信号量为0时选择阻塞一定的时间,如果超期返回-1并将errno置为ETIMEOUT。
    • int sem_post(sem_t *sem);
      信号量增一操作
    • int sem_getvalue(sem_t *restrict sem ,int *restrict valp);
      取得信号量的值,放入valp所指的内存单元中

第十六章 网络IPC:套接字

见《Unix网络编程》笔记

第十七章 高级进程间通信

Unix域套接字

头文件 <sys/socket.h> <sys/un.h>

  • 一对相互连接的Unix域套接字可以起到全双工管道的作用: 两端对读和写开放,创建方式:
    int socketpair(int domain, int type, int protocol, int sockfd[2]);
  • Unix域套接字地址格式
    struct sockaddr_un{
    sa_family_t sun_family;
    char sun_path[108];
    };
    当一个地址绑定到一个unix域套接字时,系统会用该路径名创建一个S_IFSOCK类型的文件

第十八章 终端IO

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值