linux进程和进程通信编程

Posted 小阿宁的猫猫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux进程和进程通信编程相关的知识,希望对你有一定的参考价值。

What makes the desert beautiful is that somewhere it hides a well.

沙漠之所以美丽,是因为在它的某个角落隐藏着一口井.

linux进程和进程通信编程(2)

进程间通信

1.管道通信

进程A和进程B是应用层的, 不能直接通信

管道就用于它们之间的通信, 管道存在于内核

不管有名还是无名, 只要管道里面没有内容, 使用read函数就会被阻塞

(1)有名管道

用于任何两个进程都可以

相关程序21write.c , 21read.c

mkfifo

//头文件
#include <sys/stat.h>
#include <unistd.h>


要一边写一边读, 才能读到

21write.c , 21read.c代码

21write.c

#include <stdio.h> //用于main函数
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <unistd.h> //用于close,read,write,fork
int main(int argc, char *argv[])

    char buf[32] = 0;
    int fd;
    int ret;

    if (argc < 2)
    
        printf("输入fifo文件名:\\n"); //输入参数太少了,就给提示
        printf("argc:%d\\n", argc);
    
 
    else if (argc = 2)
    
        printf("argc:%d\\n", argc);
        if (access(argv[1], F_OK) == -1)
                                        // access用于判断是否存在键盘输入的那个fifo文件
            ret = mkfifo(argv[1], 0666); //如果不存在的话,就创建一个管道文件
            if (ret == -1)
            
                printf("出错了");
            
            else
                printf("管道建好了");
        

        fd = open(argv[1], O_WRONLY);
        write(fd, "hello111", 8);
        close(fd);
    

21read.c

#include <stdio.h> //用于main函数
#include <stdlib.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h> //用于close,read,write,fork
int main(int argc, char *argv[])

    char buf[32] = 0;

    int fd;
    int ret;

    if (argc < 2)
    
        printf("输入fifo的文件名:\\n"); //输入参数太少了,就给提示
    

    else if (argc = 2)
    
        
        fd = open(argv[1], O_RDONLY);
        read(fd, buf, 32);
        printf("buf:%s\\n", buf);
        close(fd);
    
    

(2)无名管道

用于父子进程

相关程序20.c

无名管道要在子进程之前创建

如果父进程阻塞, 程序会一直卡着

父进程写了,子进程就可以读出来

20.c代码

//无名管道

#include <stdio.h> //用于main函数
#include <stdlib.h>
#include <sys/types.h> //用于pid_t
#include <sys/stat.h>
#include <sys/wait.h>

#include <unistd.h> //用于close,read,write,fork

int main()          //不含参数

    char buf[32]=0;
    
    int fd[2];   //定义管道两端的描述符,有两个
    pipe(fd);    //创建管道
    printf("fd[0]:%d\\n",fd[0]);  //打印读端的fd
    printf("fd[1]:%d\\n", fd[1]); //打印写端的fd

    pid_t pid; //定义一个pid来接收fork的返回值
    pid = fork();

    if (pid < 0)
    
        printf("创建失败");
    

    //父进程
    if (pid > 0)
    
        write(fd[1],"hello",5);             
    

    //子进程
    if (pid == 0)
    
        close(fd[1]);         //关闭写端,只用读
        read(fd[0],buf,32);
        printf("buf:%s\\n",buf);
        close(fd[0]);
    

2.信号通信

具体用到哪个信号 , 上网查就行

(1)信号发送

//头文件
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

raise

用于自己给自己发信号

相关程序22.1.c

22.1.c代码

#include <stdio.h> //用于main函数
#include <stdlib.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main()

    printf("raise之前\\n");

    raise(9);                // raise表示自己给自己发的信号,是不能被捕获的,里面的9表示终止进程
    
    printf("raise之后\\n");

kill

用于kill进程, 和kill命令作用一样

相关程序22-2.c

用22-2.c去杀死22-3.c的进程

22-2.c,22-3.c代码

22-2.c

#include <stdio.h> //用于main函数
#include <stdlib.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

int main(int argc, char *argv[])

    pid_t pid;
    int sig;

    if(argc<3)
        printf("输入被操作的进程pid和信号种类\\n");
    

    sig=atoi(argv[2]);
    pid = atoi(argv[1]);
    kill(pid,sig);

22-3.c

#include <stdio.h> //用于main函数
#include <stdlib.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main()

    while(1)
        sleep(1);
        printf("hh\\n");
    

alarm

类似于设置一个闹钟,时间到了就kill进程

相关程序22-4.c

22-4.c代码

#include <stdio.h> //用于main函数
#include <stdlib.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main()

    int i;
    alarm(4);           //表示在第4s时杀死进程

    while (1)
    
        sleep(1);
        i++;
        printf("i:%d\\n",i);
    
    

(2)信号接收

一个进程要长时间运行才能接收信号

比如用while(1) , sleep(x)(在x秒内一直运行) , pause(一直睡眠)

在进程运行时 , 按ctrl+c , 输kill, 进程就可以接收到这些信号了

用pause

用于让进程运行到一半进入休眠状态 , 会一直休眠, 用signal或ctrl+c退出

相关程序22-5.c

22-5.c代码

#include <stdio.h> //用于main函数
#include <stdlib.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main()

    printf("pause之前\\n");

    pause();               // pause表示进入休眠

    printf("pause之后\\n");

(3)信号处理

默认 (终止) , 忽略 , 捕获

用signal

相关程序22-6.c

//头文件
#include <signal.h>

默认

signal(SIGINT,SIG_DFL);
//SIGINT表示ctrl+c,SIG_DFL表示执行ctrl+c的默认操作,就是终止


忽略

signal(SIGINT,SIG_IGN);
//SIGINT表示ctrl+c,SIG_IGN表示忽略ctrl+c这个信号


捕获

signal(SIGINT,myfun);
//捕捉SIGINT这个信号,然后执行myfun里面的代码
//比如按ctrl+c,就执行另一个循环


22-6.c代码

#include <stdio.h> //用于main函数
#include <stdlib.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

// void fun(int sig) 
//     if(sig==SIGINT)
//         while (1)
//         
//             printf("hei hei\\n");
//             sleep(2);
//                 
//        
// 

int main()

    // signal(SIGINT,SIG_IGN);    //忽略
    // signal(SIGINT, SIG_DFL);     //默认
    // signal(SIGINT, fun);        //执行新的函数
    while (1)
    
        printf("hh\\n");
        sleep(2);
    

3.共享内存

用于进程间通信

创建共享内存

shmget

相关程序24-1.c

//头文件
#include <sys/ipc.h>
#include <sys/shm.h>

使用宏作为key值

使用ftok返回值作为key值

24-1.c代码

//创建共享内存,使用宏作为key值

#include <stdio.h> //用于main函数
#include <stdlib.h>

#include <sys/ipc.h>//用于shmget
#include <sys/shm.h>

#include <sys/types.h>

int main()

    int id;

    id = shmget(IPC_PRIVATE, 1024, 0777); // IPC_PRIVATE 使用宏作为key值

    if (id < 0)
    
        printf("共享内存创建失败\\n");
    
    else
        printf("id:%d\\n", id);
    

shmat

用于把内核里的共享内存映射到用户空间

shmdt

将共享内存映射的地址删除

shmctl

删除内核里面的共享内存地址

以上是关于linux进程和进程通信编程的主要内容,如果未能解决你的问题,请参考以下文章

Linux网络编程--进程间通信

Socket详解-Linux Socket编程(不限Linux)

23Linux系统编程进程间通信的集中方式

Linux Socket编程

[Linux用户空间编程-1]:Linux进程间主要的通信方式

Linux系统编程--进程间通信 ---管道篇