进程间通信

复习
线程和进程的区别
1) 线程不可以单独存在,依附于进程,进程结束,线程结束
2) 创建进程要分配所有内存(全局区、栈区、堆区、代码区),创建线程只分配栈区
void *fun(void *p)
{
    int *q = p;
    printf("%d\n", *q);
}
int a  = 100;
ptread_create(&id, NULL, fun, &a);

默认情况优先级0, 堆栈大小8M

///给线程传递参数,可以是任何类型
用pthread_create的第四个参数,
void *  可以用来赋值,但是不可以++, -- , *p

线程间同步与互斥
互斥(两个或多个线程 共同访问一个共享资源, 两个线程只能有一个同时访问)

同步(两个线程访问共享资源有先后顺序, A->B->A->B)

互斥锁(mutex)
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);

用之前加锁
pthread_mutex_lock(&mutex);
用完解锁
pthread_mutex_unlock(&mutex);

信号量
#inlcude <semaphore.h>    //sem

1 创建信号量
sem_t sem;
sem_init(&sem, 0, 3);
sem_init(&sem, 0, 1);
sem_init(&sem, 0, 0);

2 请求信号量
sem_wait(&sem);        信号值-1,  直到减到0,  阻塞
3 释放信号量
sem_post(&sem);         信号值+1
【线程间通信 使用全局变量即可】
【进程间内存都是独立的,不可以互相访问,那么进程间如何通信? linux系统从内核中拿出一块内存,供两个进程使用】
///进程间通信有  管道(无名管道和有名管道), 信号,消息队列,共享内存, 信号量, 套接字
1 管道(无名管道和有名管道)
管道的特点:
    先进先出

无名管道(只能在父子进程之间使用)
int pipe(int fd[2]);    
功能: 用于创建无名管道,一旦创建成功,就会传出2个文件描述符
fd[0] ---> 专门用于读操作(读端)
fd[1] ---> 专门用于写操作(写端)
如何读?
    read(fd[0], buf, sizeof(buf));
如何写?
    write(fd[1], buf, sizeof(buf));

例:  子进程  写入,  父进程 读出
#include <stdio.h>
#include <unistd.h>
int main()
{
    int fd[2];        //没初始化,用来保存两个文件描述符
    pipe(fd);        //传出两个文件描述符  fd[0]    fd[1]
    int pid = fork();
    if(pid == 0)
    {    //子进程
        close(fd[0]);    //子进程关闭读端
        write(fd[1], "hello", sizeof("hello"));
    }
    else if(pid > 0)
    {
        char buf[100] = { 0 };
        close(fd[1]);
        wait(NULL);
        read(fd[0], buf, sizeof(buf));    //read 是阻塞的,管道中没数据,等
        printf("read is %s\n", buf);
    }
}
///
///练习,修改上面程序,父进程循环从键盘输入数据写入管道,子进程循环读出,父进程输入'0',结束
#include <stdio.h>
#include <unistd.h>
int main()
{
    int fd[2];        //没初始化,用来保存两个文件描述符
    char buf[100] = { 0 };
    pipe(fd);        //传出两个文件描述符  fd[0]    fd[1]
    int pid = fork();
    if(pid == 0)
    {    //子进程
        close(fd[1]);    //子进程关闭读端
        while(1)
        {
            read(fd[0], buf, sizeof(buf));    //read 是阻塞的,管道中没数据,等
            if(buf[0] == '0')
                break;
            printf("read is %s\n", buf);
        }

    }
    else if(pid > 0)
    {
        close(fd[0]);
        while(1)
        {
            scanf("%s", buf);
            write(fd[1], buf, sizeof(buf));
            if(buf[0] == '0')
                break;
        }
        wait(NULL);
    }
}

2
//有名管道,通常在两个不相关的进程间通信(无名管道只能父子进程之间通信)
mkfifo  创建有名管道
#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);
参数
    pathname   管道名
    mode       管道的访问权限 (0666)

mkfifo("myfifo", 0666);   //一旦执行完mkfifo, 就会新建一个文件, 只不过这个文件创建在内存中, 访问快

打开管道
int fd = open("myfifo", O_RDWR);

读管道
read(fd, buf, sizeof(buf));

写管道
write(fd, buf, sizeof(buf));

关闭管道
close(fd);

read.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
    mkfifo("myfifo", 0666);        //可以不执行,如果管道已经存在,不新建
    int fd = open("myfifo", O_RDWR);
    if(fd > 0)
    {
        char buf[100] = { 0 };
        read(fd, buf, sizeof(buf));
        printf("read is %s\n", buf);
        close(fd);
    }
}
//wrtie.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
    int fd = open("myfifo", O_RDWR);
    if(fd > 0)
    {
        write(fd, "hello", sizeof("hello"));
        close(fd);
    }
}
gcc read.c -o read
gcc write.c -o write
./read      阻塞
开一个新终端
./write

///练习,修改上面程序,用有名管道完成:
一个进程循环从键盘输入数据写入管道,输入'0',结束,另一个进程循环读出,
///wrtie.c
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main()
{
    mkfifo("myfifo", 0666);        //创建管道, 如果管道不能存在就新建
    int fd = open("myfifo", O_RDWR);    
    if(fd > 0)
    {
        char buf[100] = { 0 };
        while(1)
        {
            gets(buf);
            write(fd, buf, sizeof(buf));
            if(buf[0] == '0')
                return 0;
        }
        close(fd);
    }
}
/读管道  read.c
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main()
{
    mkfifo("myfifo", 0666);        //创建管道
    int fd = open("myfifo", O_RDWR);    
    if(fd > 0)
    {
        char buf[100] = { 0 };
        while(1)
        {
            read(fd, buf, sizeof(buf));
            if(buf[0] == '0')
            {
                close(fd);
                return 0;
            }
            printf("read buf is %s\n", buf);            
        }
    }
}

作业:
    思维导图
    复习: 数据结构, 星期1考试
    预习: 信号

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值