zoukankan      html  css  js  c++  java
  • (linux自学笔记)进程与线程

    原文地址:

    http://www.cnblogs.com/hebaichuanyeah/p/3349061.html

     感觉linux环境下C编程主要是一堆库函数的调用。

    一.关于linux进程控制

    关于进程的创建。

    linux中fork()和vfork()函数可以创建一个子进程。

    其中vfork()创建的子进程与父进程共享数据,仅子进程先与父进程运行。

    代码:fork()创建子进程

    #include "unistd.h"
    #include "stdio.h"
    
    main()
    {
        pid_t result;
        result = fork();
        if(result == -1)
            printf("error");
        else if(result == 0)
            printf("
    
    result:%d
    in child process
    pid:%d
    
    ",result,getpid());
        else
            printf("result:%d
    in father process
    pid:%d",result,getpid());
    
    }

    代码:由于vfork()创建的子进程与父进程共享数据

    #include "stdio.h"
    #include "unistd.h"
    
    main()
    {
        pid_t pid;
        int count = 0;
        
        pid = vfork();
        
        count++;
    
        if(pid == -1)
            printf("error");
        else if(pid == 0)
            printf("in child process count is:%d
    ",count);
        else
            printf("in father process count is:%d
    ",count);
    }
        

    关于exec函数族

    exec函数族,可以在一个进程中启动另一个程序,当该进程不能为系统和用过贡献时,可以调用exec族函数执行另一个程序。

    代码:execl调用编译后的helloworld.c文件

    #include "stdio.h"
    #include "unistd.h"
    
    main()
    {
        if(execl("/home/he/program/ctest/helloworld",NULL)<0)
            printf("error
    ");
    
    }

    关于wait()与waitpid()函数。

    wait()与waitpid可以阻塞父进程。

    pid_t wait(int *status)

    waitpid原型

    代码:waitpid使用

    #include "unistd.h"
    #include "stdio.h"
    #include "sys/types.h"
    #include "sys/wait.h"
    
    main()
    {
        pid_t result;
        int pr;
    
        result = fork();
        if(result == -1)
            printf("error
    ");
        else if(result == 0)
        {
            sleep(5);
            printf("
    
    result:%d
    in child process
    pid:%d
    
    ",result,getpid());
            
        }
        else
        {
            while(!(pr=waitpid(result,NULL,WNOHANG)))
            {
                sleep(1);
                printf("the child process not exit
    ");
            }
            printf("result:%d
    in father process
    pid:%d
    
    ",result,getpid());
    
        }
    }

    关于linux守护进程

    守护进程是linux后台服务进程,该进程独立于终端,周期性执行某种任务。

    代码:编写守护进程

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<fcntl.h>
    #include<sys/types.h>
    #include<unistd.h>
    #include<sys/wait.h>
    #include<syslog.h>
             
    #define MAXFILE 65535
    int main()
    {
        pid_t pc,sid;
        int i,fd,len;
        char *buf="This is a Dameon
    ";
        len =strlen(buf);
        pc=fork();
        if(pc<0)
        {
            printf("error fork
    ");
            exit(1);
        }else if(pc>0)
        exit(0);
        openlog("demo_update",LOG_PID, LOG_DAEMON);
        if((sid=setsid())<0)
        {
            syslog(LOG_ERR, "%s
    ", "setsid");
            exit(1);
        }
        if((sid=chdir("/"))<0)
        {
            syslog(LOG_ERR, "%s
    ", "chdir");
            exit(1);
        }
        umask(0);
        for(i=0;i<MAXFILE;i++)
            close(i);
        while(1)
        {
            if((fd=open("/tmp/dameon.log",O_CREAT|O_WRONLY|O_APPEND, 0600))<0)
            {
                syslog(LOG_ERR, "open");
                exit(1);
            }
            write(fd, buf, len+1);
            close(fd);
            sleep(10);
        }
        closelog();
        exit(0);
    }

    该进程会10s周期向目标文件写入数据。

    二.进程件的通讯

    关于管道通讯

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
        int pipe_fd[2],New_process_result;
        char send_data[] = "This a message from father process";
        char receive_data[100];
    
        if(pipe(pipe_fd)<0)
        {
            printf("pipe create error
    ");
        
        }
        else 
            printf("pipe create success
    ");
        if((New_process_result=fork()) == -1)
        {
            printf("Fork error
    ");
        }
        else if(New_process_result == 0)//子进程
        {
            sleep(1);
            read(pipe_fd[0],receive_data,100);
            printf("%s",receive_data);
            putchar('
    ');
    
        }
        else//父进程
        {
            write(pipe_fd[1],send_data,strlen(send_data));
            sleep(2);
        
        }
    }

    在子进程中,打印父进程写入的数据。

    关于FIFO有名管道

    pipe管道只能用于父子进程通讯。

    FIFO可以用于任意两个进程间的通讯。

    fifo_write.c 写数据文件

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define FIFO_SERVER "/tmp/myfifo"
    
    main(int argc,char** argv)
    {
        int fd;
        char w_buf[100];
        char exitflag[] = "exit";
        int nwrite;
    
        fd = open(FIFO_SERVER,O_RDWR|O_NONBLOCK,0);
        if(fd==-1)
        {
            perror("open error");
            exit(1);
        }
        else
            printf("open success
    ");
    
        while(1)
        {
            scanf("%s",&w_buf[0]);
    
            if((nwrite=write(fd,w_buf,100))==-1)
            {
                if(errno==EAGAIN)
                    printf("The FIFO has not been read yet.Please try later
    ");
            }
            else 
                printf("write %s to the FIFO
    ",w_buf);
    
            if(!(strcmp(w_buf,exitflag)))
                exit(1);
    
        }
    
    }

    fifo_read读数据文件

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define FIFO "/tmp/myfifo"
    
    main(int argc,char** argv)
    {
        char buf_r[100];
        char exitflag[] = "exit";
        int  fd;
        int  nread;
    
        if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
            printf("cannot create fifoserver
    ");
        printf("Preparing for reading bytes...
    ");
        memset(buf_r,0,sizeof(buf_r));
        fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);
        if(fd==-1)
        {
            perror("open");
            exit(1);    
        }
        while(1)
        {
            memset(buf_r,0,sizeof(buf_r));
            read(fd,buf_r,100);    
            if(buf_r[0] == '')
                ;
            else if(!strcmp(buf_r,exitflag))
                exit(1);        
            else
                printf("read %s from FIFO
    ",buf_r);
        }    
        pause();
        unlink(FIFO);
        
    }

    在两个不同的终端中运行结果:

    exit退出程序。

    关于信号

    代码:signal键入信号(ctrl C)信号处理函数:sigint_handler

    #include "stdio.h"
    #include "signal.h"
    #include "stdlib.h"
    
    void sigint_handler(int sign_num)
    {
        if(sign_num == SIGINT)
            printf("
    "SIGINT" singal
    ");
    }
    
    int main()
    {
        signal(SIGINT,sigint_handler);
    
        pause();
    }

    代码sigaction函数

    #include "stdio.h"
    #include "signal.h"
    #include "stdlib.h"
    
    void sigint_handler(int sign_num)
    {
        if(sign_num == SIGINT)
            printf("
    "SIGINT" singal
    ");
    }
    
    int main()
    {
        struct sigaction my_signal;
    
        my_signal.sa_handler = sigint_handler;
        sigemptyset(&my_signal.sa_mask);
        my_signal.sa_flags = 0;
    
        sigaction(SIGINT,&my_signal,0);
        pause();
    
    }

     代码:父进程发生信号杀死子进程

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    int main()
    {
        pid_t pid;
    
        if((pid=fork())<0)
        {
            perror("fork");
            exit(1);
        }
        if(pid == 0) //子进程
        {
            while(1)
            {
                printf("child process runing
    ");
                sleep(1);
            }
    
    
        }
        else    //父进程
        {
            int count;
    
            for(count=0;count<5;count++)
            {
                sleep(1);
                printf("father process runing
    ");
            }
            if((count = kill(pid,SIGKILL)) == 0)
            {
                printf("
    
    father process kill:%d
    ",pid);
            }
        }
    }

    关于信号量

    同uc/os-II信号量用于对共享资源的标记

    sem_com.h文件 信号量操作

    #include "stdio.h"
    #include "unistd.h"
    #include "stdlib.h"
    #include "sys/types.h"
    #include "sys/ipc.h"
    #include "sys/shm.h"
    #include "sys/sem.h"
    
    
    extern int init_sem( int sem_id, int init_value );
    
    extern int del_sem( int sem_id );
    
    extern int sem_p( int sem_id );
    
    extern int sem_v( int sem_id );
    
    union semun
    {
        int val;
        struct semid_ds *buf;
        unsigned short *array;
        //struct seminfo *_buf;
    };

    sem_com.c文件

    #include "sem_com.h"
    
    int init_sem( int sem_id, int init_value )
    {
        union semun sem_union;
    
        sem_union.val = init_value;
    
        if ( semctl(sem_id, 0, SETVAL, sem_union) == -1 )
        {
            perror( "initialize semaphore" );
            return(-1);
        }
    
        return(0);
    }
    
    int del_sem( int sem_id )
    {
        union semun sem_union;
    
        if ( semctl(sem_id, 0,IPC_RMID, sem_union) == -1 )
        {
            perror( "Delete semaphore" );
            return(-1);
        }
    
        return(0);
    }
    
    int sem_p( int sem_id )
    {
        struct sembuf sem_b;
    
        sem_b.sem_num = 0;    /* id */
        sem_b.sem_op = -1;    /* P operation */
        sem_b.sem_flg = SEM_UNDO;
    
        if ( semop(sem_id, &sem_b, 1) == -1 )
         {
            perror( "P operation" );
            return(-1);
        }
    
        return 0;
    }
    
    int sem_v( int sem_id )
    {
        struct sembuf sem_b;
    
        sem_b.sem_num = 0;    /* id */
        sem_b.sem_op = 1;    /* V operation */
        sem_b.sem_flg = SEM_UNDO;
    
        if ( semop(sem_id, &sem_b, 1) == -1 )
        {
            perror( "V operation" );
            return(-1);
        }
    
        return 0;
    }

    主函数main.c文件 

    #include "sem_com.h"
    
    int main()
    {
        pid_t result;
        int sem_id;
    
        sem_id = semget(1,1,0666|IPC_CREAT);
    
        init_sem(sem_id, 0);
        sem_v(sem_id);
    
        result = fork();
        if(result == -1)
            printf("error");
    
        else if(result == 0)  //子进程
        {
            sem_p(sem_id);
            printf("child process get sem
    ");
            sem_v(sem_id);
        }
    
        else    //父进程
        {
            sem_p(sem_id);
            printf("father process get sem
    ");
    
            sleep(3);
            printf("father process used sem
    ");
            sem_v(sem_id);
            sleep(1);
        }
    
        exit(0);
    }

    由于父进程先运行子进程无法获取信号量,在父进程sleep中,子进程依然无法运行。

    关于共享内存

    由shmget函数创建共享内存shmat函数映射共享内存地址。

    代码:由父进程写入共享内存,子进程读取。

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int shmid,process_ret;
        char *shmadd;
    
    
        if((shmid=shmget(IPC_PRIVATE, 1024, 0666))<0)
        {
            perror("shmget");
            exit(1);
        }
    
        if((process_ret = fork()) == -1)
            printf("process creat error
    ");
        else if(process_ret == 0)//子进程
        {
            sleep(2);
            printf("in child process
    ");
            if((shmadd=shmat(shmid,0,0)) == (void*)(-1))
            {
                perror("shmat");
                exit(1);
            }
    
            //shmadd = "acc";不能这么干,shmadd地址改变了。
            shmadd[0] = 'A';
    
            printf("In child process:%s
    ",shmadd);
            if((shmdt(shmadd))<0)
            {
                perror("shmdt");
                exit(1);
            }
    
        }
        else //父进程
        {
            char share_message[] = " this is share context from father process";
            int count;
    
            printf("in father process
    ");
            if((shmadd=shmat(shmid,0,0)) == (void *)(-1))
            {
                perror("shmat");
                exit(1);
            }
            for(count=0;share_message[count]!='';count++)
                shmadd[count] = share_message[count];
    
            if((shmdt(shmadd))<0)
            {
                perror("shmdt");
                exit(1);
            }
    
    
            sleep(10);
    
        }
    
    
    }

     消息队列

     1 #include <sys/types.h>
     2 #include <sys/ipc.h>
     3 #include <sys/msg.h>
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 #include <unistd.h>
     7 #include <string.h>
     8 
     9 struct message
    10 {
    11     long msg_type;
    12     char msg_text[512];
    13 };
    14 
    15 int main()
    16 {
    17     int qid;
    18     key_t key;
    19     int len;
    20     struct message msg;
    21     char a[100];
    22 
    23     if((key=ftok(".",'a'))==-1)
    24     {
    25         perror("ftok");
    26         exit(1);
    27     }
    28     if((qid=msgget(key,IPC_CREAT|0666))==-1)  //创建消息列对
    29     {
    30         perror("msgget");
    31         exit(1);
    32     }
    33     printf("Please send a message:");
    34 
    35     scanf("%s",&msg.msg_text[0]);
    36 
    37     msg.msg_type = getpid();
    38 
    39     len = strlen(msg.msg_text);
    40 
    41     if((msgsnd(qid,&msg,len,0))<0)   //发送消息
    42     {
    43         perror("message posted");
    44         exit(1);
    45     }
    46 
    47     if(msgrcv(qid,&msg,BUFSZ,0,0)<0)   //接受消息
    48     {
    49         perror("msgrcv");
    50         exit(1);
    51     }
    52 
    53     printf("message is:%s
    ",&msg.msg_text[0]); //删除消息
    54 
    55     if((msgctl(qid,IPC_RMID,NULL))<0)
    56     {
    57         perror("msgctl");
    58         exit(1);
    59     }
    60     exit(0);
    61 }

    三.关于线程

     linux的线程,类似于uC/os-II中的“任务”。

     进程的创建

    #include "stdio.h"
    #include "pthread.h"
    #include "stdlib.h"
    
    void thread_one(void)
    {
        int i;
        for(i=0;i<10;i++)
            printf("thread one is runing
    ");
    }
    
    void thread_two(void)
    {
        int i;
    
        sleep(1);
        for(i=0;i<10;i++)
            printf("thread two is runing
    ");   
    }
    
    main()
    {
        pthread_t thread_one_id,thread_two_id;
        int resurt;
    
        if((resurt = pthread_create(&thread_one_id, NULL, (void *)thread_one, NULL))== -1)
        {
            printf("thread one creat error
    ");
            exit(1);
        }
    
        if((resurt = pthread_create(&thread_two_id, NULL, (void *)thread_two, NULL))== -1)
        {
            printf("thread two creat error
    ");
            exit(1);
        }
    
        pthread_join(thread_one_id, NULL);
        pthread_join(thread_two_id, NULL);
    }

    进程有多个属性。(优先级,分离,绑定……)

    可通过相应的函数设置创建相应属性进程。

    创建优先级为11,时间片轮转调度,绑定,分离属性的进程

        thread_one_priority = 11;
        pthread_attr_init(&thread_one_attr);
        pthread_attr_setinheritsched(&thread_one_attr, PTHREAD_EXPLICIT_SCHED);  
        pthread_attr_setschedpolicy(&thread_one_attr, SCHED_RR);
        pthread_attr_setschedparam(&thread_one_attr, (struct sched_param *)&thread_one_priority); 
    
        pthread_attr_setscope(&thread_one_attr, PTHREAD_SCOPE_SYSTEM);
        pthread_attr_setdetachstate(&thread_one_attr,PTHREAD_CREATE_DETACHED); 
    
        if((resurt = pthread_create(&thread_one_id, &thread_one_attr, (void *)thread_one, NULL)))
        {
            printf("thread one creat error
    ");
            exit(1);
        }

    互斥锁使用

    #include "stdio.h"
    #include "stdlib.h"
    #include "pthread.h"
    
    
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    
    void thread_one(void)
    {
        printf("thread_one attempt lock
    ");
        pthread_mutex_lock(&mutex);
        printf("thead_one lock success
    ");
        sleep(2);
        printf("thread_one is runing
    ");
        printf("thread_one unlock
    ");
        pthread_mutex_unlock(&mutex);
    
    }
    
    void thread_two(void)
    {
        sleep(1);
        printf("thread_two attempt lock
    ");
        pthread_mutex_lock(&mutex);
        printf("thead_two lock success
    ");
        printf("thread_two is runing
    ");
        printf("thread_two unlock
    ");
        pthread_mutex_unlock(&mutex);
    
    }
    main()
    {
        pthread_t thread_one_id,thread_two_id;
        int resurt;
    
        pthread_mutex_init(&mutex,NULL);
    
        if((resurt = pthread_create(&thread_one_id, NULL, (void *)thread_one, NULL))== -1)
        {
            printf("thread one creat error
    ");
            exit(1);
        }
    
        if((resurt = pthread_create(&thread_two_id, NULL, (void *)thread_two, NULL))== -1)
        {
            printf("thread two creat error
    ");
            exit(1);
        }
    
        pthread_join(thread_one_id, NULL);
        pthread_join(thread_two_id, NULL);
    }

    由于使用互斥锁,进程2等待进程1解锁,才能运行。

  • 相关阅读:
    匈牙利算法(二分图匹配)
    匈牙利算法(二分图匹配)
    Redis 笔记与总结6 Redis 高级应用之 事务处理、持久化操作、pub_sub、虚拟内存
    大数据的五大误区及其破解之道
    大数据的五大误区及其破解之道
    统计之 - 协方差_数据分析师
    统计之 - 协方差_数据分析师
    数据挖掘之七种常用的方法_数据分析师
    数据挖掘之七种常用的方法_数据分析师
    方差分析一般线性模型
  • 原文地址:https://www.cnblogs.com/hebaichuanyeah/p/3349061.html
Copyright © 2011-2022 走看看