zoukankan      html  css  js  c++  java
  • Linux中的进程与线程

    介绍了Linux下fork()创建进程以及使用pthread_create()创建线程的方法

    1. 基于进程的斐波那契数列

    在下面的代码中,由子进程进行斐波那契数列的输出,父进程要等待子进程输出完毕,然后再执行。

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    
    int main(int argc, char* argv[])
    {
        /**
         * pid用来保存fork()的返回值
         * n用来保存用户输入
         * f0,f1,f2用于计算斐波那契数列
         */
        pid_t pid;
        int i;
        int n;
        int f0, f1, f2;
        f0 = 0;
        f1 = 1;
    
        /**
         * 命令行参数验证
         * argv[1]表示用户输入的命令行参数,这里是5
         * 如果用户没有输入这个参数,提示用户不能为空,然后返回
         * 如果用户输入的是负数,提示用户要输入一个正数,然后返回
         * atoi()是把字符串转换为整数的方法
         */
        if (argv[1] == NULL)
        {
            fprintf(stderr, "命令行参数不能为空
    ");
            exit(-1);
        }
    
        if (atoi(argv[1]) < 0)
        {
            fprintf(stderr, "请输入一个正数
    ");
            exit(-1);
        }
    
        /**
         * 用fork()来创建新进程,
         * 返回值如果<0,表示进程创建失败,
         * 如果=0,表示该进程是一个子进程,
         * 否则,表示该进程是父进程  
         */
        pid = fork();
    
        //进程创建失败的情况,此时提示fork失败
        if (pid < 0) 
        {
            fprintf(stderr, "fork failed");
            exit(-1);
        } else if (pid == 0)
        //pid = 0表示子进程,在子进程中要完成斐波那契数列的计算输出
        {
            n = atoi(argv[1]);
            printf("参数为:%d
    ", n);
            if (n == 1) {
                printf("%d ", f0);
            } else {
                printf("%d %d ", f0, f1);
                for (i = 3; i <= n; i++) {
                    f2 = f0 + f1;
                    f0 = f1;
                    f1 = f2;
                    printf("%d ", f2);
                }
            }
            printf("
    子进程执行完毕
    ");
        } else {
            //此时表示父进程,父进程要先等待(wait)子进程执行完毕,然后再执行
            wait(NULL);
            printf("父进程执行完毕
    ");
        }
    
        return 0;
    }
    

    2. 基于线程的斐波那契数列

    在下面代码中,由子线程负责斐波那契数列的数据保存,父线程需要等待子线程的数据全部保存完毕,才能输出数据。

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>
    
    /**
     * 该函数是一个子线程函数,在这里给斐波那契数列的数组fib赋值
     * 即在子线程中把数据算好,保存在数组fib当中
     * 由于子线程和父线程可以共享数据,所以fib在子线程结束以后还存在
     */
    void *thread_fun(int *fib) 
    {
        int i;
        int num = fib[0];
        fib[1] = 0;
        fib[2] = 1;
    
        for (i = 3; i <= num; i++) {
            fib[i] = fib[i-1] + fib[i-2];
        }
    
        return NULL;
    }
    
    int main(int argc, char* argv[])
    {
        /**
         * ntid用来保存子线程的线程指针
         * err用来保存pthread_create的返回值
         * 定义了一个数组fib[50]用来存储斐波那契数列的数据
         * 用n来接受用户输入
         */
        pthread_t ntid;
        int err;
        int i;
        int n;
        int fib[50];
    
        /**
         * 命令行参数验证
         * argv[1]表示用户输入的命令行参数,这里是5
         * 如果用户没有输入这个参数,提示用户不能为空,然后返回
         * 如果用户输入的是负数,提示用户要输入一个正数,然后返回
         * atoi()是把字符串转换为整数的方法
         */
        if (argv[1] == NULL)
        {
            fprintf(stderr, "命令行参数不能为空
    ");
            exit(-1);
        }
        if (atoi(argv[1]) < 0)
        {
            fprintf(stderr, "请输入一个正数
    ");
            exit(-1);
        }
    
        /**
         * n来接收用户的输入
         * 用fib[0]来保存用户输入的数据,以方便下一步传参数
         */
        n = atoi(argv[1]);
        fib[0] = n;
    
        /**
         * 创建一个新的线程,第一个参数用来保存线程的指针,第二个参数设置为NULL
         * 第三个参数表示子线程要执行的函数,第四个参数为函数的参数
         * 我们把fib这个数组传过去
         */
        err = pthread_create(&ntid, NULL, thread_fun, (void *)fib);
        
        //err!=0表示线程创建失败的情况,此时提示错误
        if (err != 0) {
            fprintf(stderr, "线程创建失败
    ");
            exit(-1);
        }
        //如果执行到这里,表示子线程创建成功,但是父线程需要等待子线程执行完毕
        //pthread_join()方法表示父线程要等待子线程ntid的执行,ntid是刚才创建线程时保存子线程的指针
        pthread_join(ntid,NULL);
    
        /**
         * 到这里表示子线程已经执行完毕了,所有数据应该都有了
         * 那么我们可以将他们打印出来了
         */
        printf("子线程执行完毕,由父线程输出数据:
    ");
        for(i = 1; i<= n; i++) {
            printf("%d ", fib[i]);
        }
    
        printf("
    ");
    }
    
  • 相关阅读:
    Linux学习之网络基础
    C# 随笔
    最牛B的编码套路
    c++ Primer 第七章不熟悉知识点总结
    oracle求表的倒数二行数据
    c++ Primer 第六章不熟悉知识点总结
    c++ Primer 第五章不熟悉知识点总结
    c++ Primer 第四章不熟悉知识点总结
    c++ Primer 第三章不熟悉知识点总结
    骑驴找马
  • 原文地址:https://www.cnblogs.com/Kassadin/p/6648993.html
Copyright © 2011-2022 走看看