(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("\n\nresult:%d\nin child process\npid:%d\n\n",result,getpid());
    else
        printf("result:%d\nin father process\npid:%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\n",count);
    else
        printf("in father process count is:%d\n",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\n");

}

 

 

 

关于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\n");
    else if(result == 0)
    {
        sleep(5);
        printf("\n\nresult:%d\nin child process\npid:%d\n\n",result,getpid());
        
    }
    else
    {
        while(!(pr=waitpid(result,NULL,WNOHANG)))
        {
            sleep(1);
            printf("the child process not exit\n");
        }
        printf("result:%d\nin father process\npid:%d\n\n",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\n";
    len =strlen(buf);
    pc=fork();
    if(pc<0)
    {
        printf("error fork\n");
        exit(1);
    }else if(pc>0)
    exit(0);
    openlog("demo_update",LOG_PID, LOG_DAEMON);
    if((sid=setsid())<0)
    {
        syslog(LOG_ERR, "%s\n", "setsid");
        exit(1);
    }
    if((sid=chdir("/"))<0)
    {
        syslog(LOG_ERR, "%s\n", "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\n");
    
    }
    else 
        printf("pipe create success\n");
    if((New_process_result=fork()) == -1)
    {
        printf("Fork error\n");
    }
    else if(New_process_result == 0)//子进程
    {
        sleep(1);
        read(pipe_fd[0],receive_data,100);
        printf("%s",receive_data);
        putchar('\n');

    }
    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\n");

    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\n");
        }
        else 
            printf("write %s to the FIFO\n",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\n");
    printf("Preparing for reading bytes...\n");
    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] == '\0')
            ;
        else if(!strcmp(buf_r,exitflag))
            exit(1);        
        else
            printf("read %s from FIFO\n",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("\n\"SIGINT\" singal\n");
}

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("\n\"SIGINT\" singal\n");
}

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\n");
            sleep(1);
        }


    }
    else    //父进程
    {
        int count;

        for(count=0;count<5;count++)
        {
            sleep(1);
            printf("father process runing\n");
        }
        if((count = kill(pid,SIGKILL)) == 0)
        {
            printf("\n\nfather process kill:%d\n",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\n");
        sem_v(sem_id);
    }

    else    //父进程
    {
        sem_p(sem_id);
        printf("father process get sem\n");

        sleep(3);
        printf("father process used sem\n");
        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\n");
    else if(process_ret == 0)//子进程
    {
        sleep(2);
        printf("in child process\n");
        if((shmadd=shmat(shmid,0,0)) == (void*)(-1))
        {
            perror("shmat");
            exit(1);
        }

        //shmadd = "acc";不能这么干,shmadd地址改变了。
        shmadd[0] = 'A';

        printf("In child process:%s\n",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\n");
        if((shmadd=shmat(shmid,0,0)) == (void *)(-1))
        {
            perror("shmat");
            exit(1);
        }
        for(count=0;share_message[count]!='\0';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\n",&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\n");
}

void thread_two(void)
{
    int i;

    sleep(1);
    for(i=0;i<10;i++)
        printf("thread two is runing\n");   
}

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\n");
        exit(1);
    }

    if((resurt = pthread_create(&thread_two_id, NULL, (void *)thread_two, NULL))== -1)
    {
        printf("thread two creat error\n");
        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\n");
        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\n");
    pthread_mutex_lock(&mutex);
    printf("thead_one lock success\n");
    sleep(2);
    printf("thread_one is runing\n");
    printf("thread_one unlock\n");
    pthread_mutex_unlock(&mutex);

}

void thread_two(void)
{
    sleep(1);
    printf("thread_two attempt lock\n");
    pthread_mutex_lock(&mutex);
    printf("thead_two lock success\n");
    printf("thread_two is runing\n");
    printf("thread_two unlock\n");
    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\n");
        exit(1);
    }

    if((resurt = pthread_create(&thread_two_id, NULL, (void *)thread_two, NULL))== -1)
    {
        printf("thread two creat error\n");
        exit(1);
    }

    pthread_join(thread_one_id, NULL);
    pthread_join(thread_two_id, NULL);
}

 

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

posted @ 2013-10-02 01:38  默默地EEer  阅读(773)  评论(0编辑  收藏  举报