进程间通信

解决进程间通信需要借助双方都可以访问的第三方

第三方可以是:

1:普通文件:P1进程<---文件--->P2进程

2.管道

3.信号

4.消息队列

5.信号量

6.共享内存

7.网络---socket

1.管道

管道:利用了文件系统接口(操作管道时:open read write close),只是文件内容(实体)存在内核/内存中(而不是存在与硬盘中)。

管道有两种:无名管道有名管道

1.1无名管道

无名管道:没有名字,本质是没有i_node——i_no:de是一个文件的唯一标识,没有i_node在文件系统中就找不到这个文件。

无名管道的创建:pipe

NAME
       pipe - create pipe

SYNOPSIS
       #include <unistd.h>

       int pipe(int pipefd[2]);
		pipefd[2]:2个整型元素得数组--存储管道文件描述符
            保存了管道的两端:pipefd[0] 读端  pipefd[1] 写端
       返回值:
         成功,返回0
         失败,返回-1,并且errno被设置

PS:

  • 无名管道在使用过程中,适用于亲缘进程之间的通信

  • 管道的通信方式为半双工,同时进行收发容易造成自收自发。所以如果双方需要同时进行通信(全双工)则需要使用两根管道

  • 通信方式:

    全双工:通信双方可以同时进行数据接收和发送,比如:视频电话

    半双工:通信双方,同一时刻,只能有一方进行发送,另一方接收,比如:对讲机

    单工:通信双方中,一方固定为发送端,一方则固定为接收端。 信息只能沿一个方向传输,比如:广播

1.2 有名管道

有名管道:有名字,本质就是在文件系统存在i_node<能够通过路径进行访问>,可以用于非亲缘进程之间的通信。但是有名管道的内容(实体)仍然存在于内核中。

创建一个有名管道:mkfifo

NAME
       mkfifo - make a FIFO special file (a named pipe) -- 命名/有名管道

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

       int mkfifo(const char *pathname, mode_t mode);
		pathname:带路径的文件名 --- 你要创建的有名管道 名字以及创建位置
            "/home/china/test.pipe"  OK
            "./test.pipe"            不一定行 有名管道不能够放在共享文件夹中
        mode:权限
            ①:S_IRUSR | S_IWUSR
               S_IRGRP
               S_IROTH
            ②:0664
        返回值:
            成功,返回0
            失败,返回-1,并且errno被设置

有名管道 和 无名管道 数据收发方式类似,只是有名管道可以用于非亲缘进程之间的通信。同样的是不能同时进行收发。

/*
    FIFO特殊文件(命名管道)类似于管道,不同之处在于它是作为文件系统的一部分访问的。它可以被多个进程打开,用于读或写。当进程通过FIFO交换数据时,内核在内部传递所有数据,而不将其写入文件系统。因此,FIFO特殊文件在文件系统上没有内容;文件系统条目仅仅用作参考点,以便进程可以使用文件系统中的名称访问管道。

内核为每个至少由一个进程打开的FIFO特殊文件维护一个管道对象。在数据可以传递之前,FIFO必须在两端打开(读和写)。通常,打开FIFO块,直到另一端也被打开。

进程可以在非阻塞模式下打开FIFO。在这种情况下,即使没有人在写端打开,为只读打开也会成功,而在ENXIO(没有这样的设备或地址)下,为只写打开失败,除非另一端已经打开。

在Linux下,为读写打开FIFO将在阻塞和非阻塞模式下都成功。POSIX不定义此行为。这可以用来打开一个FIFO写,而没有可用的读者。使用连接的两端与自己通信的进程应该非常小心,以避免死锁。
*/

/*
    fifo 的两端都必须同时打开,fifo才能正常使用
        以非阻塞的形式打开 读端,打开会成功,即使写端未打开
        以非阻塞的形式打开 写端,打开会失败,并且 errno == ENXIO,除非读端被打开
*/

2.信号

信号也是IPC  通信手段之一,他不是用来传递数据,它的本质是一个整数,不同的信号值代表不同的含义。

# 可发送的信号 
china@ubuntu:~$ kill -l
 1) SIGHUP	    2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	    7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	    12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	    22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	    28) SIGWINCH	29) SIGIO	    30) SIGPWR
31) SIGSYS	    34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

信号:


	   信号名	    信号值     信号行为   具体内容
 	   Signal     Value     Action   Comment
       ──────────────────────────────────────────────────────────────────────
       SIGHUP        1       Term    Hangup detected on controlling terminal
                                     or death of controlling process
									 控制终端 的挂起操作 或者控制终端进程死亡时
									 控制终端 上的所有进程都会收到 SIGHUP
       SIGINT        2       Term    Interrupt from keyboard
                                     键盘输入 中断信号  cltr + c
       SIGQUIT       3       Core    Quit from keyboard
                                     键盘输入 退出信号  cltr + \
       SIGILL        4       Core    Illegal Instruction
                                     使用了非法指令 
       SIGABRT       6       Core    Abort signal from abort(3)
       					             调用 abort函数产生
       SIGFPE        8       Core    Floating-point exception
       							     浮点运算异常
       SIGKILL       9       Term    Kill signal  干掉相应进程
       SIGSEGV      11       Core    Invalid memory reference
                                     非法内存访问  段错误
       SIGPIPE      13       Term    Broken pipe: write to pipe with no
                                     readers; see pipe(7)
                                     往管道写入数据时 没有读端
       SIGALRM      14       Term    Timer signal from alarm(2)
                                     闹钟信号  由alarm函数产生
       SIGTERM      15       Term    Termination signal
       SIGUSR1   30,10,16    Term    User-defined signal 1
       SIGUSR2   31,12,17    Term    User-defined signal 2
       SIGCHLD   20,17,18    Ign     Child stopped or terminated
       SIGCONT   19,18,25    Cont    Continue if stopped
       SIGSTOP   17,19,23    Stop    Stop process
       SIGTSTP   18,20,24    Stop    Stop typed at terminal  
                                          ctrl+z
       SIGTTIN   21,21,26    Stop    Terminal input for background process
       SIGTTOU   22,22,27    Stop    Terminal output for background process

对信号的处理,通常有三种方式:

1.捕获这个信号:把一个信号和用户自定义的信号处理函数联系起来。

2.默认行为:收到这个信号,采用系统默认的行为。

3.忽略:收到这个信号不进行处理

2.2信号相关的API

捕获信号:关键是将原先系统默认的行为(函数地址)替换为用户自定义的函数——signal

NAME
       signal - ANSI C signal handling

SYNOPSIS
       #include <signal.h>

       /* 
       sighandler_t 新的类型 函数指针类型 可以定义指针变量 用于指向一个 没有返回值,.
       且参数为int类型的函数
       */
       typedef void (*sighandler_t)(int);

       sighandler_t signal(int signum, sighandler_t handler);
			signum:信号值 --- 你要捕获的信号
			handler:函数地址 对应的函数 需要是无返回值 且参数为int类型
                ①:自定义的处理函数
                ②:SIG_IGN 忽略该信号
                ③:SIG_DFL 默认
       返回值:
          成功,返回之前的信号处理方式 
          失败,返回SIG_ERR,errno被设置  
                
 /* The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored                 SIGKILL SIGSTOP 不能被捕获 被阻塞 被忽略  */

kill:发送一个信号给对应的进程

NAME
       kill - send signal to a process
		
SYNOPSIS
       #include <sys/types.h>
       #include <signal.h>

       int kill(pid_t pid, int sig);
		pid:pid 指定信号的接收进程
            pid > 0 指定的进程
            pid == 0 和调用进程同组的所有进程
            pid == -1 发送给所有进程(有权限发送的)
            pid < -1  发送给 进程组id == abs(pid)的那个组的所有进程
        sig:指定发送的信号值
       返回值:
          成功,返回0
          失败,返回-1,并且errno被设置  
            
      kill -9 1456 <=等价于=> kill(1456, 9);      

alarm:闹钟  设置一个闹钟

NAME
       alarm - set an alarm clock for delivery of a signal

SYNOPSIS
       #include <unistd.h>

       unsigned int alarm(unsigned int seconds);
		seconds:设置闹钟时长
       返回值:
            返回上一个闹钟的剩余秒数
            
PS:一个进程只有一个闹钟        

raise:发送信号给自己        pause:等待一个信号

NAME
       raise - send a signal to the caller
		发送一个信号给自己
SYNOPSIS
       #include <signal.h>

       int raise(int sig);
			sig:你要发送的那个信号的值
NAME
       pause - wait for signal
			等待一个信号
SYNOPSIS
       #include <unistd.h>

       int pause(void);

       pause()  returns  only when a signal was caught and the signal-catching
       function returned.  In this case, pause() returns -1, and errno is  set
       to EINTR.

3.共享内存

共享内存:其实就是通过映射的方式使得多个进程可以同时访问同一块内存,换而言之就是将一块内存同时映射到多个进程的进程地址空间中,借此这些进程就可以通过这块内存进行数据交流。这块内存就称之为共享内存

管道和共享内存:

共享内存效率比管道要高

共享内存实现方式:

1.POSIX标准共享内存——mmap

2.System V标准 共享内存

3.1System V操作流程

1.创建一个System V IPC对象的Key——>ftok

2.创建/打开相应的IPC对象(msg、shm、sem)

3.映射到进程中

4.通过System V读写接口,进行数据传递

5.解除映射和关闭这个IPC对象

3.2相应API函数

ftok

NAME
       ftok  -  convert  a pathname and a project identifier to a System V IPC
       key
SYNOPSIS
       #include <sys/types.h>
       #include <sys/ipc.h>

       key_t ftok(const char *pathname, int proj_id);
			pathname:路径名 --- 在文件系统中要存在
            proj_id:工程ID号
	   返回值:
           成功,返回一个 system V IPC唯一的key
           失败,返回-1,并且errno被设置     

shmget

NAME
       shmget - allocates a System V shared memory segment
		创建/打开一个共享内存
SYNOPSIS
       #include <sys/ipc.h>
       #include <sys/shm.h>

       int shmget(key_t key, size_t size, int shmflg);
		key:system V ipc对象的key
        size:共享区域的大小
            创建时,size != 0,size的大小,一般是4096的整数倍 PAGE_SIZE
            打开一个已存在的共享内存时,size == 0
        shmflg:打开方式
            ①:创建打开  IPC_CREAT | 权限位(0664/S_IRUSR)
            ②:打开 0
       返回值:
          成功,返回一个共享内存的id,这个id是共享内存的唯一标识
          失败,返回-1,并且errno被设置

shmat/shmadt

NAME
       shmat, shmdt - System V shared memory operations
		映射/解除映射
SYNOPSIS
       #include <sys/types.h>
       #include <sys/shm.h>

       void *shmat(int shmid, const void *shmaddr, int shmflg);
		shmid:你要映射的那个共享区域的ID
        shmaddr:你要映射到进程的哪个区域,一般为NULL 让系统自行分配
        shmflg:对映射区域的操作方式
            SHM_RDONLY 只读
            0		   读写
       返回值:
            成功,返回映射区域的首地址
           	失败,返回 (void *)-1,errno 被设置
            
	   int shmdt(const void *shmaddr);
			shmaddr:要解除的映射区域的首地址
       返回值:
          成功,返回0
          失败,返回-1,errno被设置      

shmctl

NAME
       shmctl - System V shared memory control

SYNOPSIS
       #include <sys/ipc.h>
       #include <sys/shm.h>

       int shmctl(int shmid, int cmd, struct shmid_ds *buf);
		shmid:你要控制的那个共享内存的ID
        cmd:你要做什么操作
            IPC_RMID 删除指定的共享内存
            IPC_SET  设置共享内存的属性
            IPC_STAT 获取共享内存的属性
        buf:存储第二个参数的相关内容
            if cmd == IPC_RMID  buf == NULL 
       返回值:
          成功,返回0
          失败,返回-1,errno被设置 

4.信号量

引入:对共享内存的操作:假定有一块共享内存PSHM指针指向了这块共享内存,有两个进程p1,p2,将其映射到了进程地址空间。此时,p1进程和p2进程对共享内存的操作(int *pSHM)有这样的一部分代码:

for(int i=0; i<100000; i++)
    (*pSHM)++;
// 最终得到的结果不是20w ---》对共享内存的操作 (*pSHM)++不是原子操作(原子操作:一定会执行完的操作),由于时间片的原因 会在任意的时刻结束对共享内存的操作

4.1 信号量机制

什么是信号量?作用是什么?

信号量(semphore)是一种用于提供不同 进程间/线程间 同步的一种机制。

进程 / 线程 : 并发的实体

同步:并发实体之间 相互等待 相互制约 ,有条件的访问

信号量的目的是 为了保护共享资源,使得共享资源有序访问

使用信号量时,需要明确谁是共享资源,必须要存在共享资源(产生竞争),才需要用到信号量。

信号量机制:其实是一种约定,进程之间需要按照规则去访问共享资源。

约定(规则):

进程A 和 进程B 都需要访问一个 互斥(同时只有由一个进程访问)设备,可以使用信号量来表示这个设备是否可以被访问。

约定:只要有进程访问 这个设备,先访问信号量,如果信号量的访问标志为 YES,则先设置信号量的访问标志为NO,然后再去访问设备,访问完设备之后,将信号量置为YES。

PS:使用信号量来访问共享内存时 一定要遵守约定,否则会出现异常

4.2 信号量操作流程

①:创建一个信号量 / 信号灯 / 锁

        

信号量 实际上就是一个整数,信号量的创建时可以指定信号量的初始值:

sem(信号量) 的初始值 == 5,表示该信号量所保护的共享资源可以同时被5个进程/线程 访问

sem(信号量) 的初始值 == 1,表示该信号量所保护的共享资源是互斥资源,也称这个信号量为互斥信号量

YES ---> sem value > 0

NO ---> sem value == 0

②:等待一个信号量 上锁

等待一个信号量:等待这个信号量是否可以被访问 把这个操作 称之为 P操作 (荷兰语 proberen),也可以称之为上锁

该操作 会测试这个信号量的值,如果值 == 0,就会等待,如果这个值>0表示可以访问,访问时会将信号量的值-1(上锁),继续往下执行 操作临界区《操作共享资源的代码块》的代码

③:释放一个信号量 解锁

释放一个信号量:称之为 V操作 荷兰语-verhogen,或者解锁,该操作将信号量的值+1

4.3 相关API

4.3.1 System V信号量

操作流程:获得key--->创建/打开信号量---》P/V操作--》删除/控制

system V:所设计的信号量 叫做信号量集

semget:

NAME
       semget - get a System V semaphore set identifier

SYNOPSIS
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>

       int semget(key_t key, int nsems, int semflg);
			key:system V对应的IPC对象的key
            nsems:你要创建的信号量集中的信号量的个数
                如果是打开一个已存在的信号量集,nsem 给0 即可
                信号量集中的信号量的个数 一旦创建就不能被改变
            semflg:方式
                ①:创建 IPC_CREAT | 权限(S_IRUSR / 0664)
                ②:打开 0
        返回值:
            成功,返回信号量的id,id是该信号量的唯一标识
            失败,返回-1,并且errno被设置

semctl:信号量被创建之后应当 立即赋予初值

NAME
       semctl - System V semaphore control operations

SYNOPSIS
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>

       int semctl(int semid, int semnum, int cmd, ...);
			semid:你要操作的信号量的id
            semnum:指定你要操作的信号量集中的那一信号量
            cmd:你要对该信号量作何种操作
                cmd == GETVAL 获取 semnum 指定的那个信号量的值
                       SETVAL 设置 semnum 指定的那个信号量的值
                       GETALL 获取 semid  指定的那个信号量集中所有信号量的值
                       SETALL 设置 semid  指定的那个信号量集中所有信号量的值
                       IPC_RMID 删除该信号量集
                ...
            ...:
                if cmd == IPC_RMID 第四个参数就不要了
                   cmd == GETVAL 第四个参数就不要了,可以通过函数返回值返回
                   cmd == SETVAL 第四个参数是要设置的值
                   cmd == GETALL 第四个参数用来接收所有信号量的值
                    unsigned short getvals[nsems];
                   cmd == SETALL 第四个参数用来保存所有待设置的信号量的值 
                    unsigned short setvals[nsems];
       返回值:
           if cmd == GETVAL
               返回值的含义就是相应的信号量的值
           if cmd == IPC_RMID
               成功,返回0
               失败,返回-1,并且errno被设置

P/V操作:semop

NAME
       semop, semtimedop - System V semaphore operations

SYNOPSIS
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>
		struct sembuf{
           unsigned short sem_num;  /* semaphore number */ 
            	信号量的编号
           short          sem_op;   /* semaphore operation */
            	对信号量的操作
                    > 0    V操作
                    ==0    尝试操作
                    < 0    P操作
           short          sem_flg;  /* operation flags */
                操作方式
                    == 0   默认方式,P操作 如果获取不了,阻塞
                    == IPC_NOWAIT 非阻塞版本,如果P操作获取不了 直接退出
                    == SEM_UNDO   撤销,为了防止进程退出 带锁退出
                    使用 SEM_UNDO 这个标志 内核会额外记录该进程对信号量的所有PV操作,然后在进程退出时,会还原相应的信号量操作
        }
       int semop(int semid, struct sembuf *sops, size_t nsops);
		semid:你要进行p操作的信号量集
      	sops:指定对信号量集中的哪一个信号量做P/V操作
        nsops:指定第二个参数的个数
       返回值:
          成功,返回0
          失败,返回-1,并且errno被设置  
		
            timed:超时等待
       int semtimedop(int semid, struct sembuf *sops, size_t nsops,
                      const struct timespec *timeout);
			前三个参数都是和semop一样的
		timeout:设置超时时间
       struct timespec{
           time_t tv_sec;
           long   tv_nsec;
       };         

示例:超时等待 5s

// 超时5s
struct timespec timedout = {.tv_sec = 5, .tv_nsec = 0};
// p操作 阻塞版本 第0号信号量
struct sembuf sem = {.sem_num = 0, .sem_op = -1, .sem_flg = 0};
semtimedop( semid, &sem, 1, &timedout);

4.3.2 死锁

        哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。哲学家就餐问题有时也用米饭和筷子而不是意大利面和餐叉来描述,因为很明显,吃米饭必须用两根筷子。 哲学家从来不交谈,这就很危险,可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。

死锁问题的必要条件:

  1. 互斥性:一个资源职能被一个任务访问

  2. 请求和保持条件:一个任务对请求的资源被占用阻塞时,已经占用资源不释放

  3. 不可剥夺:一个任务在释放之前,其他的任务无法剥夺它所占用的资源

  4. 循环等待:当发生死锁时,任务进入死循环,永久阻塞

解决死锁问题:破坏死锁形成的必要条件(只要破坏其中一个即可),有一个经典的算法---银行家算法

system V标准 信号量集 ---》对于信号量集中的信号量<5个信号量> ---》获取其中的两个信号量,对于system V的做法是 必要要全部获取,否则就等待(并且不会保持某个信号量)

4.3.2 POSIX信号量

POSIX信号量 分为 :有名信号量无名信号量

有名信号量:在文件系统中 有一个文件接口(i_node),内容存在于内核。可以用于进程间的同步。

无名信号量:没有名字,可以存在于进程的地址空间中 / 共享内存中。

如果 无名信号量存在于 进程的地址空间中,那么只能用于进程内部的任务的同步。

如果 无名信号量存在于 共享内存中,那么能用于进程之间任务的同步。

创建一个POSIX信号量:sem_open

NAME
       sem_open - initialize and open a named semaphore

SYNOPSIS
       #include <fcntl.h>           /* For O_* constants */
       #include <sys/stat.h>        /* For mode constants */
       #include <semaphore.h>
        
        sem_t *sem_open(const char *name,int oflag);
    
        sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned in value);



       name:带路径的文件名,要创建/打开的那个有名信号量
                路径要求:以/开头, 并且只能由一个 /
                	"/POSIX.SEM"  OK
                    "/home/china/POSIX.sem" ERR
            oflag:打开方式
                O_CREAT 创建
                0       打开
            mode:权限 --- 创建时才需要指定
                0664 
                S_IRUSR | S_IWUSR
            value:指定信号量的初始值    
		返回值:
            成功,返回一个信号量指针
            失败,返回 SEM_FAILED,errno被设置

PS:有名信号量创建成功之后,可以在 /dev/shm 目录下查看有名信号

无名信号量的创建:sem_init

NAME
       sem_init - initialize an unnamed semaphore

SYNOPSIS
       #include <semaphore.h>

       int sem_init(sem_t *sem, int pshared, unsigned int value);
		sem:指向一个要初始化的无名信号量
        pshared:该信号量的共享方式
            0 进程内部共享 sem 指向进程内部的空间
            1 进程间共享   sem 指向内核共享区域
        value:初始化的信号量的值 
       返回值:
           成功,返回0
           失败,返回-1,并且errno被设置 
       Link with -pthread.

PV操作:sem_wait / sem_post

NAME
       sem_wait, sem_timedwait, sem_trywait - lock a semaphore

SYNOPSIS
       #include <semaphore.h>
    
		// 阻塞版本的p操作
       int sem_wait(sem_t *sem);
		// 非阻塞版本的p操作
       int sem_trywait(sem_t *sem);
        // (绝对时间的)超时等待的p操作
       int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
		sem:你要对哪个信号量进行p操作
        abs_timeout:绝对时间的超时等待
       返回值:
           成功,返回0
           失败,返回-1,并且errno被设置   
            
       相对时间:相对于当前时间来说
            2个小时之后就下课了  
       绝对时间:绝对时间
            2024-7-12-17-30 下课    
       5s钟超时等待:
       先要获取当前的系统时间:
            struct timespec timedout;
            int clock_gettime(clockid_t clk_id, struct timespec *tp);
        	timeout.tv_sec+=5; 
            
       Link with -pthread.
NAME
       sem_post - unlock a semaphore

SYNOPSIS
       #include <semaphore.h>

       int sem_post(sem_t *sem);
			sem:你要进行V操作的信号量
       返回值:
           成功,返回0
           失败,返回-1,并且errno被设置     

其他操作:sem_getvalue\sem_close\sem_unlink\sem_destroy

NAME
       sem_getvalue - get the value of a semaphore

SYNOPSIS
       #include <semaphore.h>

       int sem_getvalue(sem_t *sem, int *sval);
			sem:表示你要获取的那个信号量
            sval:用来保存获取到的信号量的值
       返回值:
           成功,返回0
           失败,返回-1,并且errno被设置  
                
NAME
       sem_close - close a named semaphore
		关闭一个被打开的有名信号量
SYNOPSIS
       #include <semaphore.h>

       int sem_close(sem_t *sem);

NAME
       sem_unlink - remove a named semaphore
		删除一个有名信号量
SYNOPSIS
       #include <semaphore.h>

       int sem_unlink(const char *name);
			name:删除一个文件  带路径的文件名
NAME
       sem_destroy - destroy an unnamed semaphore
		销毁一个无名信号量
SYNOPSIS
       #include <semaphore.h>

       int sem_destroy(sem_t *sem);

PS:使用POSIX信号量时,编译时需要加上编译选项 -pthread

例如:gcc posixsem.c -o posixsem -pthread

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值