Linux进程与线程通信

一、创建一个pipe

pipe函数需要传入一个大小为2的int数组,并且返回一个创建结果,若为-1则表示创建失败,否则则创建成功。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

using namespace std;

int main() {
    int result = -1;
    int fd[2], nbytes;
    result = pipe(fd);
    if (result == -1) {
        printf("fail to create pip\n" );
        exit(-1);
    } else {
        printf( "pipe create success\n" );
    }
    return 0;
}

运行结果

jiangxiaoju@jiangxiaoju-MS-7B51:~/Code/CLionProjects/osepx$ gcc exp1.c -o exp1
jiangxiaoju@jiangxiaoju-MS-7B51:~/Code/CLionProjects/osepx$ ./exp1 
pipe create success

二、请提供由fork()创建两个生产进程和两个消费进程,它们之间通过pipe()传递信息

fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事。

用fork()创建进程,若返回值为0,则表示父进程,否则则是子进程的pid。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/file.h>
#include <stdlib.h>
#include <sys/wait.h>


char buffer[1024]; //
char msg[1024];
int fd[2];
int *read_fd=&fd[0];
int *write_fd=&fd[1];

void producer(int pid){
    printf("producer % d is running.\n",pid);
    close(*read_fd);
    int i;
    for(i=0;i<10;i++){
        sleep(3);
        if(pid==1)
            strcpy(msg,"producer1\0");
        else
            strcpy(msg,"producer2\0");
        if(write(*write_fd,buffer,strlen(msg)+1)==-1)
            printf("write to pipe erroe.\n");

    }
    close(*write_fd);
    printf("prodecuer %d is over!\n",pid);
    exit(pid);
}

void consumer(int pid){
    close(*write_fd);
    printf("consumer %d is running.\n",pid);
    if(pid==1)
        strcpy(msg,"consumer1\0");
    else
        strcpy(msg,"consumer2\0");
    while(true){
        sleep(1);
        strcpy(buffer,"product\0");
        if(read(*read_fd,buffer,strlen(buffer)+1)==0)
            break;
        printf("consumer %d get %s,while the msg is %s\n",pid,buffer,msg);
    }
    printf("consumer %d is over.\n",pid);
    exit(pid);
}

int main(){
    // pid_t 用来保持进程 id
    pid_t pid1,pid2,pid3,pid4;
    int result=pipe(fd);
    if(result==-1){
        printf("pipe create error.\n");
        exit(-1);
    }else{
        printf("pipe create successfully.\n");
        // 利用fork()创建四个线程
        if((pid1=fork())==0)
            producer(1);
        if((pid2=fork())==0)
            producer(2);
        if((pid3=fork())==0)
            consumer(1);
        if((pid4=fork())==0)
            consumer(2);
    }
    //关闭pipe
    close(*read_fd);
    close(*write_fd);
    int i,pid,status;
    for(i=0;i<4;i++){
        pid=wait(&status);
    }

    return 0;
}

运行结果

每次的运行结果不一定会相同

jiangxiaoju@jiangxiaoju-MS-7B51:~/Code/CLionProjects/osepx$ gcc exp2.c -o exp2
jiangxiaoju@jiangxiaoju-MS-7B51:~/Code/CLionProjects/osepx$ ./exp2 
pipe create successfully.
producer  1 is running.
producer  2 is running.
consumer 2 is running.
consumer 1 is running.
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 get ,while the msg is consumer2
prodecuer 1 is over!
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
prodecuer 2 is over!
consumer 2 get ,while the msg is consumer2
consumer 1 get ,while the msg is consumer1
consumer 2 is over.
consumer 1 is over.

三、用clone()创建四个轻进程(线程),用参数指明共享内存等资源,通过共享内存模拟生产消费问题,利用pthread_mutex_lock(), pthread_mutex_unlock()等函数实现对共享存储区访问的互斥.

#include <sched.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t mutex;
sem_t product;
sem_t warehouse;

char buffer[8][1024];
int bp = 0;

int producer(void *args) {
    int id = *((int *) args);
    int i;
    for (int i = 0; i < 10; ++i) {
        sleep(i + 1);
        sem_wait(&warehouse);
        if (id == 0)
            strcpy(buffer[bp], "product1\0");
        else
            strcpy(buffer[bp], "product2\0");
        bp++;
        printf("producer %d produce %s in %d\n",id,buffer[bp-1],bp);
        sem_post(&product);

    }
    printf("producer %d is over\n",id);
    exit(id);
}

int consumer(void *args) {
    int id = *((int *) args);
    int i;
    for (int i = 0; i < 10; ++i) {
        sleep(10-i);
        sem_wait(&product);
        pthread_mutex_lock(&mutex);
        bp--;
        printf("consumer %d get %s in %d.\n",id,buffer[bp],bp+1);
        strcpy(buffer[bp],"clear.\0");
        pthread_mutex_unlock(&mutex);
        sem_post(&warehouse);
    }
    printf("consumer %d is over.\n",id);
    exit(id);
}

int main(int argc, char **argv) {

    pthread_mutex_init(&mutex, NULL);
    sem_init(&product, 0, 0);
    sem_init(&warehouse, 0, 8);
    int clone_flag, arg, retval;
    char *stack;
    clone_flag = CLONE_VM | CLONE_SIGHAND | CLONE_FS | CLONE_FILES;
    int i;
    for (int i = 0; i < 2; ++i) {
        arg = i;
        stack = (char *) malloc(4096);
        retval = clone(& producer, &(stack[4095]), clone_flag, (void *) &arg);
        stack = (char *) malloc(4096);
        retval = clone(& consumer, &(stack[4095]), clone_flag, (void *) &arg);
    }

    return 0;

}

运行结果
这里要特别注意,编译的时候要加上-pthread参数,否则会出现如下错误.

jiangxiaoju@jiangxiaoju-MS-7B51:~/Code/CLionProjects/osepx$ gcc exp3.cpp -o exp3
/tmp/ccMplIVh.o:在函数‘producer(void*)’中:
exp3.cpp:(.text+0x39):对‘sem_wait’未定义的引用
exp3.cpp:(.text+0xd5):对‘sem_post’未定义的引用
/tmp/ccMplIVh.o:在函数‘consumer(void*)’中:
exp3.cpp:(.text+0x13b):对‘sem_wait’未定义的引用
exp3.cpp:(.text+0x1ba):对‘sem_post’未定义的引用
/tmp/ccMplIVh.o:在函数‘main’中:
exp3.cpp:(.text+0x222):对‘sem_init’未定义的引用
exp3.cpp:(.text+0x236):对‘sem_init’未定义的引用
collect2: error: ld returned 1 exit status

还有一点,文件名后缀要用.cpp
否则编译的时候会出现如下错误

jiangxiaoju@jiangxiaoju-MS-7B51:~/Code/CLionProjects/osepx$ gcc exp3.c -o exp3
exp3.c: In function ‘main’:
exp3.c:59:18: error: ‘CLONE_VM’ undeclared (first use in this function)
     clone_flag = CLONE_VM | CLONE_SIGHAND | CLONE_FS | CLONE_FILES;
                  ^
exp3.c:59:18: note: each undeclared identifier is reported only once for each function it appears in
exp3.c:59:29: error: ‘CLONE_SIGHAND’ undeclared (first use in this function)
     clone_flag = CLONE_VM | CLONE_SIGHAND | CLONE_FS | CLONE_FILES;
                             ^
exp3.c:59:45: error: ‘CLONE_FS’ undeclared (first use in this function)
     clone_flag = CLONE_VM | CLONE_SIGHAND | CLONE_FS | CLONE_FILES;
                                             ^
exp3.c:59:56: error: ‘CLONE_FILES’ undeclared (first use in this function)
     clone_flag = CLONE_VM | CLONE_SIGHAND | CLONE_FS | CLONE_FILES;
                                                        ^
exp3.c:66:18: warning: implicit declaration of function ‘clone’ [-Wimplicit-function-declaration]
         retval = clone(& producer, &(stack[4095]), clone_flag, (void *) &arg);
                  ^

正确运行结果如下

jiangxiaoju@jiangxiaoju-MS-7B51:~/Code/CLionProjects/osepx$ gcc exp3.cpp -pthread -o exp3
jiangxiaoju@jiangxiaoju-MS-7B51:~/Code/CLionProjects/osepx$ ./exp3 
jiangxiaoju@jiangxiaoju-MS-7B51:~/Code/CLionProjects/osepx$ producer 3 produce product2 in 1
producer 4197456 produce product2 in 2
producer 3 produce product2 in 3
product2 in 4
producer 3 produce product2 in 5
producer 4197456 produce product2 in 6
consumer 4197456 get product2 in 6.
consumer 4197456 get product2 in 5.
producer 3 produce product2 in 5
producer 4197456 produce product2 in 6
producer 3 produce product2 in 7
producer 4197456 produce product2 in 8
consumer 4197456 get product2 in 8.
consumer 4197456 get product2 in 7.
producer 3 produce product2 in 7
producer 4197456 produce product2 in 8
consumer 4197456 get product2 in 8.
consumer 4197456 get product2 in 7.
producer 3 produce product2 in 7
producer 3 produce product2 in 7
producer 4197456 produce product2 in 8
consumer 4197456 get product2 in 8.
consumer 4197456 get product2 in 7.
producer 3 produce product2 in 7
producer 4197456 produce product2 in 8
consumer 4197456 get product2 in 8.
consumer 4197456 get product2 in 7.
consumer 4197456 get product2 in 6.
consumer 4197456 get product2 in 5.
producer 3 produce product2 in 5
producer 3 produce product2 in 5
producer 4197456 produce product2 in 6
consumer 4197456 get product2 in 6.
consumer 4197456 get product2 in 5.
consumer 4197456 get product2 in 4.
consumer 4197456 get product2 in 3.
consumer 4197456 get product2 in 2.
consumer 4197456 get product2 in 1.
producer 3 produce product2 in 1
producer 3 produce product2 in 1
producer 4197456 produce product2 in 2
producer 3 is over
producer 4197456 is over
consumer 4197456 get product2 in 2.
consumer 4197456 is over.

猜你喜欢

转载自blog.csdn.net/qq_43058685/article/details/105727594