博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(linux自学笔记)进程与线程
阅读量:5119 次
发布时间:2019-06-13

本文共 12883 字,大约阅读时间需要 42 分钟。

原文地址:

 感觉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
#include
#include
#include
#include
#include
#include
#include
#define MAXFILE 65535int 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

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

 

 

 

二.进程件的通讯

关于管道通讯

#include 
#include
#include
#include
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 
#include
#include
#include
#include
#include
#include
#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 
#include
#include
#include
#include
#include
#include
#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 
#include
#include
#include
#include
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 
#include
#include
#include
#include
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 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 9 struct message10 {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解锁,才能运行。

转载于:https://www.cnblogs.com/hebaichuanyeah/p/3349061.html

你可能感兴趣的文章
cassandra vs mongo (1)存储引擎
查看>>
Visual Studio基于CMake配置opencv1.0.0、opencv2.2
查看>>
遍历Map对象
查看>>
MySQL索引背后的数据结构及算法原理
查看>>
#Leetcode# 209. Minimum Size Subarray Sum
查看>>
SDN第四次作业
查看>>
DM8168 DVRRDK软件框架研究
查看>>
django迁移数据库错误
查看>>
yii 跳转页面
查看>>
洛谷 1449——后缀表达式(线性数据结构)
查看>>
Data truncation: Out of range value for column 'Quality' at row 1
查看>>
Dirichlet分布深入理解
查看>>
字符串处理
查看>>
HtmlUnitDriver 网页内容动态抓取
查看>>
ad logon hour
查看>>
获得进程可执行文件的路径: GetModuleFileNameEx, GetProcessImageFileName, QueryFullProcessImageName...
查看>>
证件照(1寸2寸)拍摄处理知识汇总
查看>>
罗马数字与阿拉伯数字转换
查看>>
Eclipse 反编译之 JadClipse
查看>>
Python入门-函数
查看>>