当前位置: 首页 > news >正文

资讯网站模版百度收录最新方法

资讯网站模版,百度收录最新方法,海报在线设计平台,c#做asp.net网站学习参考博文: 进程间的五种通信方式介绍Linux 信号介绍 Linux系统编程学习相关博文 Linux系统编程——文件编程的学习Linux系统编程——进程的学习Linux系统编程——线程的学习Linux系统编程——网络编程的学习 Linux系统编程——进程间通信的学习 一、概述1. 无…

学习参考博文:

  1. 进程间的五种通信方式介绍
  2. Linux 信号介绍

Linux系统编程学习相关博文

  1. Linux系统编程——文件编程的学习
  2. Linux系统编程——进程的学习
  3. Linux系统编程——线程的学习
  4. Linux系统编程——网络编程的学习

Linux系统编程——进程间通信的学习

  • 一、概述
    • 1. 无名管道和有名管道的区别
    • 2. 当打开一个FIFO时,是否设置非阻塞标志(O_NONBLOCK)的区别:
    • 3. 消息队列
    • 4. 共享内存
    • 5. 信号
    • 6. 信号量
  • 二、进程间通信API
  • 三、API介绍
    • 1. pipe函数
    • 2. mkfifo函数
    • 3. msgget函数
    • 4. msgsnd函数
    • 5. msgrcv函数
    • 6. msgctl函数
    • 7. shmget函数
    • 8. shmat函数
    • 9. shmdt函数
    • 10. shmctl函数
    • 11. signal函数
    • 12. kill函数
    • 13. sigaction函数
    • 14. sigqueue函数
    • 15. semget函数
    • 16. semctl函数
    • 17. semop函数
  • 四、API的使用例子
    • 1. pipe函数
    • 2. mkfifo函数
    • 3. msgget、msgsnd、msgrcv、msgctl函数
    • 4. shmget、shmat、shmdt、shmctl函数
    • 5. signal函数
    • 6. kill函数
    • 7. sigaction函数
    • 8. sigqueue函数
    • 9. semget、semctl、semop函数

一、概述

常规学习Linux系统编程的内容是复杂且繁多的,不推荐刚开始接触代码的朋友去学习,所以介绍Linux系统编程的目的主要是以应用开发为主。

进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。

IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。

1. 无名管道和有名管道的区别

  1. 无名管道是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间),它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。
  2. 有名管道可以在无关的进程之间交换数据,与无名管道不同。

2. 当打开一个FIFO时,是否设置非阻塞标志(O_NONBLOCK)的区别:

  1. 若没有指定O_NONBLOCK(默认),只读 open 要阻塞到某个其他进程为写而打开此 FIFO。类似的,只写 open 要阻塞到某个其他进程为读而打开它。

  2. 若指定了O_NONBLOCK,则只读 open 立即返回。而只写 open 将出错返回 -1 如果没有进程已经为读而打开该 FIFO,其errno置ENXIO。

3. 消息队列

  1. 消息队列,是消息的链接表,存放在内核中。
  2. 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。

4. 共享内存

  1. 共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
  2. 因为多个进程可以同时操作,所以需要进行同步。
  3. 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。

5. 信号

  1. 每个信号都有一个名字和编号,这些名字都以“SIG”开头,例如“SIGIO ”、“SIGCHLD”等等。
  2. 信号定义在signal.h头文件中,信号名都定义为正整数。
  3. 具体的信号名称可以使用kill -l来查看信号的名字以及序号,信号是从1开始编号的,不存在0号信号。kill对于信号0又特殊的应用。
  4. 信号的处理有三种方法,分别是:忽略、捕捉和默认动作

6. 信号量

信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

  1. 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
  2. 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
  3. 每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。(P操作相当于拿钥匙,V操作相当于放钥匙)
  4. 支持信号量组。

二、进程间通信API

在Linux系统中,操作系统提供了一系列的API,详细看下图

1. 管道
创建无名管道		pipe()
创建有名管道		mkfifo()
2. 消息队列
创建或打开消息队列	msgget()
添加消息				msgsnd()
读取消息				msgrcv()
控制消息队列			msgctl()
3. 共享内存
创建或获取共享内存		shmget()
将共享内存映射到当前进程的虚拟地址空间	shmat()
断开与共享内存的连接		shmdt()
控制共享内存的相关信息	shmctl()
4. 信号
信号处理函数		入门版 signal() / 高级版 sigaction()
信号发送函数		入门版 kill() / 高级版 sigqueue()
5. 信号量
创建或获取信号量组		semget()
控制信号量的相关信息		semctl()
对信号量组进行操作		semop()

三、API介绍

1. pipe函数

#include <unistd.h>int pipe(int pipefd[2]);1. 函数功能:创建无名管道
2. 形参说明:
pipefd[2]:一个管道建立时,它会创建两个文件描述符:fd[0]为读而打开,fd[1]为写而打开。
3. 返回值:成功返回0,失败返回-1

2. mkfifo函数

#include <sys/types.h>
#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);1. 函数功能:创建有名管道
2. 形参说明:
pathname:文件路径名
mode:与open函数中的mode相同。一旦创建了一个FIFO,就可以用一般的文件I/O函数去操作它。(忘记的可以去文件编程学习篇章回顾下)
3. 返回值:成功返回0,失败返回-1

3. msgget函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgget(key_t key, int msgflg);1. 函数功能:创建或打开消息队列
2. 形参说明
key:键值key,可自己写死,也可用ftok函数生成(ftok函数具体看API使用例子了解)
msgflg:- 这个参数可以是单独的IPC_CREAT,也可以是IPC_CREAT|IPC_EXCL,但IPC_EXCL单独使用没有意义- 如果单独使用IPC_CREAT(记得附加权限),或者flg为0:创建一个消息队列,如果创建的消息队列已经存在,则返回已经存在的队列ID,不存在则创建 - IPC_CREAT | IPC_EXCL:如果不存在消息队列,则创建,如果已经有了消息队列,则返回-1
3. 返回值:成功返回队列ID,失败返回-1

4. msgsnd函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);1. 函数功能:添加消息
2. 形参说明:
msqid:队列ID
msgp:msgp参数是一个指针,指向调用者定义的结构体,其一般形式如下:struct msgbuf {long mtype;       /* message type, must be > 0 */char mtext[1];    /* message data */};mtext字段是一个数组(或其他结构),其大小由非负整数值msgsz指定。允许零长度的消息(即没有mtext字段)。mtype字段必须是严格的正整数值。接收进程可以使用此值进行消息选择
msgsz:指定msgp结构体里边mtext参数的大小
msgflg:默认是0
3. 返回值:成功返回0,失败返回-1

5. msgrcv函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);1. 函数功能:读取消息
2. 形参说明:
msqid:队列ID
msgp:msgp参数是一个指针,指向调用者定义的结构体,其一般形式如下:struct msgbuf {long mtype;       /* message type, must be > 0 */char mtext[1];    /* message data */};
msgsz:读取数据的大小
msgtyp:mtype字段必须是严格的正整数值。接收进程可以使用此值进行消息选择
msgflg:msgflg参数是一个位掩码,由以下零个或多个标志组合而成:· IPC_NOWAIT如果队列中没有请求类型的消息,则立即返回· MSG_EXCEPT当msgtyp大于0时,用于读取消息类型与msgtyp不同的队列中的第一条消息。· MSG_NOERROR如果消息文本长度超过msgsz字节,则截断消息文本。· 为0时是默认状态,当没有消息类型与msgtyp相同的队列发送信息时,则一直阻塞
3. 返回值:成功返回消息数据的长度,失败返回-1

6. msgctl函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgctl(int msqid, int cmd, struct msqid_ds *buf)1. 函数功能:控制消息队列
2. 形参说明:
msqid:队列ID
cmd:IPC_RMID————从内核中删除消息队列(其他参数请自行查阅)
buf:控制消息队列时数据处理的结构体(默认是NULL)
3. 返回值:成功返回0,失败返回-1

7. shmget函数

#include <sys/ipc.h>
#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);1. 函数功能:创建或获取共享内存
2. 形参说明:
key:键值key,可自己写死,也可用ftok函数生成(ftok函数具体看API使用例子了解)
size:当用shmget函数创建一段共享内存时,必须指定其 size;而如果引用一个已存在的共享内存,则将 size 指定为0 。
shmflg:- 这个参数可以是单独的IPC_CREAT,也可以是IPC_CREAT|IPC_EXCL,但IPC_EXCL单独使用没有意义- 如果单独使用IPC_CREAT(记得附加权限),或者flg为0:创建一个共享内存,如果创建的共享内存已经存在,则返回已经存在的共享内存ID,不存在则创建 - IPC_CREAT | IPC_EXCL:如果不存在共享内存,则创建,如果已经有了共享内存,则返回-1
3. 返回值:成功返回共享内存ID,失败返回-1

8. shmat函数

#include <sys/types.h>
#include <sys/shm.h>void *shmat(int shmid, const void *shmaddr, int shmflg);1. 函数功能:将共享内存映射到当前进程的虚拟地址空间
2. 形参说明:
shmid:共享内存ID
shmaddr:该参数常用的是NULL。如果shmadr为NULL,系统选择一个合适的(未使用的)地址来附加该段
shmflg:该形参作用是权限附加,常用的是0。如果为0,系统默认映射进来的共享内存为可读可写权限
3. 返回值:成功返回指向共享内存的指针,失败返回-1

9. shmdt函数

#include <sys/types.h>
#include <sys/shm.h>int shmdt(const void *shmaddr);1. 函数功能:断开与共享内存的连接
2. 形参说明:
shmaddr:映射后返回共享内存的指针
3. 返回值:成功返回0,失败返回-1

10. shmctl函数

#include <sys/ipc.h>
#include <sys/shm.h>int shmctl(int shmid, int cmd, struct shmid_ds *buf);1. 函数功能:控制共享内存的相关信息
2. 形参说明:
shmid:共享内存ID
cmd:命令参数。常用的是IPC_RMID(从系统中删除该共享内存)
buf:该参数是卸载共享内存后所返回的一些信息。不关心为NULL
3. 返回值:成功返回0,失败返回-1

11. signal函数

#include <signal.h>typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);1. 函数功能:信号处理函数
2. 形参说明:
signum:监听的信号(kill -l参看)
handler:收到信号后处理的函数函数原型:typedef void (*sighandler_t)(int);

12. kill函数

#include <sys/types.h>
#include <signal.h>int kill(pid_t pid, int sig);1. 函数功能:信号发送函数
2. 形参说明:
pid:发送信号时对方的pid号
sig:要发送的信号(kill -l参看)
3. 返回值:成功返回0,失败返回-1

13. sigaction函数

#include <signal.h>int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);1. 函数功能:信号处理函数(带数据)
2. 形参说明:
signum:监听的信号(kill -l参看)
act:收到信号后处理的函数结构体原型:struct sigaction {void     (*sa_handler)(int);void     (*sa_sigaction)(int, siginfo_t *, void *);sigset_t   sa_mask;int        sa_flags;void     (*sa_restorer)(void);};上面结构体里第二个函数指针第二个struct siginfo结构体的相关信息siginfo_t {int      si_signo;    /* Signal number */int      si_errno;    /* An errno value */int      si_code;     /* Signal code */int      si_trapno;   /* Trap number that causedhardware-generated signal(unused on most architectures) */pid_t    si_pid;      /* Sending process ID */uid_t    si_uid;      /* Real user ID of sending process */int      si_status;   /* Exit value or signal */clock_t  si_utime;    /* User time consumed */clock_t  si_stime;    /* System time consumed */sigval_t si_value;    /* Signal value */int      si_int;      /* POSIX.1b signal */void    *si_ptr;      /* POSIX.1b signal */int      si_overrun;  /* Timer overrun count; POSIX.1b timers */int      si_timerid;  /* Timer ID; POSIX.1b timers */void    *si_addr;     /* Memory location which caused fault */int      si_band;     /* Band event */int      si_fd;       /* File descriptor */}
oldact:该参数是数据备份。默认为NULL
3. 返回值:成功返回0,失败返回-1

14. sigqueue函数

#include <signal.h>int sigqueue(pid_t pid, int sig, const union sigval value);1. 函数功能:信号发送函数(带数据)
2. 形参说明:
pid:发送信号时对方的pid号
sig:要发送的信号(kill -l参看)
value:发送的数据联合体原型:union sigval {int   sival_int;void *sival_ptr;};
3. 返回值:成功返回0,失败返回-1

15. semget函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semget(key_t key, int nsems, int semflg);1. 函数功能:创建或获取一个信号量组
2. 形参说明:
key:键值key,可自己写死,也可用ftok函数生成(ftok函数具体看API使用例子了解)
nsems:信号量个数
semflg:- 这个参数可以是单独的IPC_CREAT,也可以是IPC_CREAT|IPC_EXCL,但IPC_EXCL单独使用没有意义- 如果单独使用IPC_CREAT(记得附加权限),或者flg为0:创建一个共享内存,如果创建的共享内存已经存在,则返回已经存在的共享内存ID,不存在则创建 - IPC_CREAT | IPC_EXCL:如果不存在共享内存,则创建,如果已经有了共享内存,则返回-1
3. 返回值:成功返回信号量集ID,失败返回-1

16. semctl函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semctl(int semid, int semnum, int cmd, ...);1. 函数功能:控制信号量的相关信息
2. 形参说明:
semid:信号量集id
semnum:操控哪个信号量
cmd:命令参数。常用的是SETVAL这个函数有三个或四个参数,具体取决于cmd。当有四个时,第四个具有类型联合semur调用程序必须按如下方式定义这个联合体: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) */};3. 返回值:失败返回-1

17. semop函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semop(int semid, struct sembuf *sops, unsigned nsops)1. 函数功能:对信号量组进行操作
2. 形参说明:
semid:信号量集id
sops:sops所指向的数组中的每个nsop元素都指定了要在单个信号量上执行的操作。该结构体的元素类型为struct sembuf,包含以下成员:unsigned short sem_num;  /* semaphore number */short          sem_op;   /* semaphore operation */short          sem_flg;  /* operation flags */
nsops:信号量集个数(决定第二个参数个数)该函数的使用例子:struct sembuf sops[2];int semid;/* Code to set semid omitted */sops[0].sem_num = 0;        /* Operate on semaphore 0 */sops[0].sem_op = 0;         /* Wait for value to equal 0 */sops[0].sem_flg = 0;sops[1].sem_num = 0;        /* Operate on semaphore 0 */sops[1].sem_op = 1;         /* Increment value by one */sops[1].sem_flg = 0;if (semop(semid, sops, 2) == -1) {perror("semop");exit(EXIT_FAILURE);}3. 返回值:成功返回0,失败返回-1

四、API的使用例子

1. pipe函数

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <unistd.h>6 7 int main()8 {9 //  int pipe(int pipefd[2]);10 11     int pid = 0;12     int fd[2] = {0};13     char buf[128] = {0} ;14 15     if(pipe(fd) == -1){ //创建管道16         printf("create pipe failed\n");17         perror("why");18     }19 20     pid = fork(); //创建子进程21 22     if(pid < 0){ 23         printf("create child failed\n");24         perror("why");25     }26     else if(pid > 0){ //父进程27         sleep(1);28 29         printf("This is father\n");30         close(fd[0]); //关闭读端31         write(fd[1], "Hello World", strlen("Hello World")); //写入数据32 33         wait(NULL);34     }35     else{ //子进程36         printf("This is child\n");37         close(fd[1]); //关闭写端38         read(fd[0], buf, sizeof(buf)); //读取数据39         printf("read data: %s\n", buf);40 41         exit(0);42     }43 44     return 0;45 }

2. mkfifo函数

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <sys/types.h>6 #include <sys/stat.h>7 #include <errno.h>8 #include <fcntl.h>9 10 int main()11 {12 //  int mkfifo(const char *pathname, mode_t mode);13     int fd = 0;14 15     if((mkfifo("./file", 0600) == -1) && errno != EEXIST){ //创建管道16         printf("create failed\n");17         perror("why");18     }19 20     fd = open("./file", O_RDONLY);21 22     return 0;23 }

3. msgget、msgsnd、msgrcv、msgctl函数

接收端demo

  1 #include <stdio.h>2 #include <errno.h>3 #include <string.h>4 #include <stdlib.h>5 6 #include <sys/types.h>7 #include <sys/ipc.h>8 #include <sys/msg.h>9 10 // 1. int msgget(key_t key, int msgflg);11 // 2. int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);12 // 3. ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);13 14 struct msgbuf {15     long mtype;       /* message type, must be > 0 */16     char mtext[128];    /* message data */17 }18 19 int main()20 {21     int msgId;22 23     key_t key;24 25     struct msgbuf readBuf;26     struct msgbuf sendBuf = {988, "Welcome your coming"};27 28     key = ftok(".", 23); //获取key29     printf("key = 0x%x\n", key);30 31     msgId = msgget(key, IPC_CREAT|0777); //创建消息队列32 33     if(msgId == -1){34         printf("creat quene failed\n");35         perror("why");36     }37 38     msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 888, 0); //读取消息39     printf("get message from quene, content: %s\n", readBuf.mtext);40 41     msgsnd(msgId, &sendBuf, sizeof(sendBuf.mtext), 0); //发送消息42 43     msgctl(msgId, IPC_RMID, NULL); //删除消息队列44 45     return 0;46 }

发送端

  1 #include <stdio.h>2 #include <errno.h>3 #include <string.h>4 #include <stdlib.h>5 6 #include <sys/types.h>7 #include <sys/ipc.h>8 #include <sys/msg.h>9 10 // 1. int msgget(key_t key, int msgflg);11 // 2. int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);12 // 3. ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);13 14 struct msgbuf {15     long mtype;       /* message type, must be > 0 */16     char mtext[128];    /* message data */17 };18 19 int main()20 {21     int msgId;22 23     key_t key;24 25     struct msgbuf readBuf;26     struct msgbuf sendBuf = {888, "This is content from quene"};27 28     key = ftok(".", 23); //获取key29     printf("key = 0x%x\n", key);30 31     msgId = msgget(key, IPC_CREAT|0777); //创建消息队列32 33     if(msgId == -1){34         printf("creat quene failed\n");35         perror("why");36     }37 38     msgsnd(msgId, &sendBuf, sizeof(sendBuf.mtext), 0); //发送消息39     printf("Send over!\n");40 41     msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 988, 0); //读取消息42     printf("get message from msgGet, content: %s\n", readBuf.mtext);43 44     msgctl(msgId, IPC_RMID, NULL);45 46     return 0;47 }

4. shmget、shmat、shmdt、shmctl函数

接收端

   1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <sys/ipc.h>6 #include <sys/shm.h>7 #include <sys/types.h>8 9 // 1. int shmget(key_t key, size_t size, int shmflg);10 // 2. void *shmat(int shmid, const void *shmaddr, int shmflg);11 // 3. int shmdt(const void *shmaddr);12 // 4. int shmctl(int shmid, int cmd, struct shmid_ds *buf);13 14 int main()15 {16     int shmid;17     char *shmaddr;18 19     key_t key;20 21     key = ftok(".", 1); //获取key22 23     shmid = shmget(key, 1024*4, 0); //获取共享内存24 25     shmaddr = shmat(shmid, NULL, 0); //映射26 27     printf("read: %s\n", shmaddr);28 29     shmdt(shmaddr); //断开共享内存30 31     printf("quit\n");32 33     return 0;34 }

发送端

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <sys/ipc.h>6 #include <sys/shm.h>7 #include <sys/types.h>8 9 // 1. int shmget(key_t key, size_t size, int shmflg);10 // 2. void *shmat(int shmid, const void *shmaddr, int shmflg);11 // 3. int shmdt(const void *shmaddr);12 // 4. int shmctl(int shmid, int cmd, struct shmid_ds *buf);13 14 int main()15 {16     int shmid;17     char *shmaddr;18 19     key_t key;20 21     key = ftok(".", 1); //获取key22 23     shmid = shmget(key, 1024*4, IPC_CREAT|0666); //创建共享内存24 25     if(shmid == -1){26         perror("create shm failed");27         exit(-1);28     }29 30     shmaddr = shmat(shmid, NULL, 0); //映射31 32     strcpy(shmaddr, "Hello World"); //写入数据33     printf("write..\n");34     sleep(5);35 36     shmdt(shmaddr); //断开共享内存37 38     shmctl(shmid, IPC_RMID, NULL); //删除共享内存39 40     printf("quit\n");41 42     return 0;43 }

5. signal函数

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <signal.h>6 7 // typedef void (*sighandler_t)(int);8 // 1. sighandler_t signal(int signum, sighandler_t handler);9 10 void handler(int signum) //处理函数11 {12     switch(signum){13         case 2:14             printf("signum = %d\n", signum);15             printf("never quit\n");16 17             break;18         case 9:19             printf("signum = %d\n", signum);20             printf("never quit\n");21 22             break;23         case 10:24             printf("signum = %d\n", signum);25             printf("never quit\n");26 27             break;28         default:29             printf("signum = %d\n", signum);30             printf("never quit\n");31 32             break;33     }34 }35 36 int  main()37 {38     signal(SIGHUP, handler); //捕获SIGHUP信号39     signal(SIGINT, handler); //捕获SIGINT信号40     signal(SIGKILL, handler); //捕获SIGKILL信号41     signal(SIGUSR1, handler); //捕获SIGUSR1信号42 43     while(1);44 45     return 0;46 }

6. kill函数

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <signal.h>6 #include <sys/types.h>7 8 // typedef void (*sighandler_t)(int);9 // 1. sighandler_t signal(int signum, sighandler_t handler);10 // 2. int kill(pid_t pid, int sig);11 12 int  main(int argc, char **argv)13 {14     int pid;15     int signum;16     char cmd[32] = "/0";17 18     if(argc < 3){19         printf("please input three param\n");20         exit(-1);21     }22 23     signum = atoi(argv[1]); //将字符串转换成整型数(第二个参数)24     pid = atoi(argv[2]); //将字符串转换成整型数(第三个参数)25 26     sprintf(cmd, "kill -%d %d", signum, pid);27     //kill(pid, signum); //发送指令28 29     system(cmd); //发送指令30 31     return 0;32 }

7. sigaction函数

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <sys/types.h>6 #include <unistd.h>7 #include <signal.h>8 9 // 1. int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);10 11 void handler(int signum, siginfo_t *info, void *context) //处理函数12 {13     printf("\nsignum = %d\n", signum);14 15     if(context != NULL){16         printf("get data: %d\n", info->si_int);17         printf("get data: %d\n", info->si_value.sival_int);18         printf("from: %d\n",info->si_pid);19     }20 }21 22 int main()23 {24     struct sigaction act;25 26     printf("pid = %d\n", getpid());27 28     act.sa_sigaction = handler;29     act.sa_flags = SA_SIGINFO; //如果在sa_flags中指定了SA SIGINFO,则sa _sigaction(而不是sa_handler)指定signum的信号处理函数。30 31     sigaction(SIGUSR1, &act, NULL); 捕获SIGUSR1信号32 33     while(1);34 35     return 0;36 }

8. sigqueue函数

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <sys/types.h>6 #include <unistd.h>7 #include <signal.h>8 9 // 1. int sigqueue(pid_t pid, int sig, const union sigval value);10 11 int main(int argc, char **argv)12 {13     int pid;14     int signum;15 16     pid = atoi(argv[2]); //将字符串转换成整型数(第三个参数)17     signum = atoi(argv[1]); //将字符串转换成整型数(第二个参数)18 19     union sigval value;20     value.sival_int = 100; //发送的整形数据21 22     sigqueue(pid, signum, value); //发送函数23 24     printf("pid = %d\n", getpid()); //打印pid号25 26     return 0;27 }

9. semget、semctl、semop函数

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <sys/types.h>6 #include <sys/ipc.h>7 #include <sys/sem.h>8 #include <unistd.h>9 10 // 1. int semget(key_t key, int nsems, int semflg);11 // 2. int semctl(int semid, int semnum, int cmd, ...);12 // 3. int semop(int semid, struct sembuf *sops, unsigned nsops);13 14 union semun {15     int              val;    /* Value for SETVAL */16     struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */17     unsigned short  *array;  /* Array for GETALL, SETALL */18     struct seminfo  *__buf;  /* Buffer for IPC_INFO19                                 (Linux-specific) */20 };21 22 void pGetKey(int semid) //拿钥匙23 {24     struct sembuf sop;25 26     sop.sem_num = 0;        /* Operate on semaphore 0 */27     sop.sem_op = -1;        /* Wait for value to equal 0 */28     sop.sem_flg = SEM_UNDO;29 30     semop(semid, &sop, 1); //操作信号量31 32     printf("Get key\n");33 }34 35 void vPutBackKey(int semid) //放钥匙36 {37     struct sembuf sop;38 39     sop.sem_num = 0;        /* Operate on semaphore 0 */40     sop.sem_op = 1;        /* Wait for value to equal 0 */41     sop.sem_flg = SEM_UNDO;42 43     semop(semid, &sop, 1); //操作信号量44 45     printf("Put back key\n");46 }47 48 int main()49 {50     int pid;51     int semid;52     key_t key;53 54     union semun value;55 56     key = ftok(".", 23); //获取key57 58     //创建/获取一个信号量59     semid = semget(key, 1, IPC_CREAT|0666); //创建信号量集60 61     value.val = 0; //初始时盒子里没钥匙62 63     //控制信号量集64     semctl(semid, 0, SETVAL, value); //信号量集初始化65 66     pid = fork(); //创建子进程67 68     if(pid > 0){ //父进程69         // 拿钥匙——如果盒子里没钥匙,父进程出于阻塞状态70         pGetKey(semid); //拿钥匙71         printf("This is father\n");72         // 放钥匙73         vPutBackKey(semid); //放钥匙74     }75     else if(pid == 0){ //子进程76         printf("This is child\n");77         // 放钥匙——因初始化时盒子里没钥匙,无论是不是父进程先运行它都会处于阻塞状态,等子进程把放入钥匙后父进程才能拿钥匙开门78         vPutBackKey(semid); //放钥匙79     }80     else{81         printf("fork error\n");82     }83 84     return 0;85 }
http://www.ds6.com.cn/news/33747.html

相关文章:

  • 找郴州一家做网站的公司电话营销网站建设教学
  • 网站流量 转化率seo的全称是什么
  • asp动态网站开发课程设计全网营销是什么
  • 仙桃网站设计关键词搜索排名
  • 网站开发的背景与环境做网站排名优化的公司
  • 手机网页图片显示不出来宁波seo教程网
  • 阿里云做网站怎么样搜索 引擎优化
  • 做西服的网站网站制作app
  • 网站短信验证怎么做百度搜索下载app
  • 一个公司做两个网站网络互联网推广
  • 上海php网站开发中国知名网站排行榜
  • wordpress评论框制作百度优化排名
  • 温州做阀门网站公司网站不收录怎么办
  • 梅州企业网站建设公司全网
  • 义乌品牌网站建设seo群发软件
  • 网站区域名是什么意思汕头seo网站推广
  • 免费建站平台的源码互联网优化
  • 现代网站开发技术世界球队最新排名
  • 邵阳网站推广谷歌关键词排名优化
  • 永兴集团网站产品市场调研怎么做
  • 网站建设论文设计关键词自动生成器
  • 青岛营销型网站制作免费发广告网站
  • 我想做个网站seo网络推广外包公司
  • 唐山网站制作网络公司百度客服人工电话24小时
  • 注册外贸网站有哪些问题泉州全网营销优化
  • dw做不了动态网站asp搜索引擎的优化和推广
  • 厦门有设计网站的吗昆明seo推广外包
  • 兰州网络推广服务合同seo兼职外包
  • 网站建设售后报价下载一个百度导航
  • 易语言如何做网站登录国外网站设计