linux 进程编程
来源:互联网 发布:枪神纪刷枪软件2016 编辑:程序博客网 时间:2024/06/14 08:11
一、进程的操作
1、进程的创建
父进程与子进程之间的关系是管理与被管理,当子进程终止时,父进程不一定终止;父进程终止时子进程一定终止。
Linux系统启动时只有一个进程:init进程,进程号为1。
可以通过getpid()获取自身运行的进程ID,通过getppid()获取父进程的ID。
这两个函数在头文件<unistd.h>当中。
printf("Process ID :%d\n",(int)getpid());
2、fork()函数
创建经常一般有两种方法:system()和fork()函数。
pid_t fork();
一个进程通过fork()函数会创建一个子进程,这个子进程和父进程只有进程ID不同,其他都一样,若子进程创建失败,则fork()函数返回-1,若创建成功则在子进程中返回0,在父进程中返回子进程的ID。
#include<stdio.h>#include<unistd.h>#include<sys/types.h>int main(){ pid_t child_pid; child_pid =fork(); switch (child_pid) { case -1: printf("Create Process failed!\n"); break; case 0: printf("child Proces with ID %d\n",(int)getpid()); break; default: printf("Parent Process with %d,child Proces Id:%d\n",(int)getppid(),getpid()); break; } return 0;}
3、进程的管理与调度
Linux下管理进程的命令有:at bg fg jobs kill ps pstree top noce sleep
4、进程的终止
子进程运行完毕后,并不立即释放所占用的进程控制表项,而作为僵进程存在,直到父进程终止或者调用wait()函数终止。
pid_t wait(int *status)
wait()函数会让父进程阻塞自己,分析已经退出的子进程,wait()函数会返回子进程结束状态值,如果没有找到一个这样的子进程,会一直阻塞。status 会储存子进程结束信息。
另一个函数waitpid(),可以设定参数设置让指定的子进程终止。
pid_t waitpid(pid_t pid,int *status,int option);WIFEXITED(status)
能够判断子进程是否正常结束,如果正常结束,则返回个非0值。
#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>int main(){ pid_t child_pid,pid; int status; child_pid=fork(); switch (child_pid) { case -1: printf("Creadte Process failed\n"); break; case 0: printf("child Process with ID %d\n",(int)getpid()); break; default: printf("Parent Process with ID %d,Child Process with ID %d",(int)getpid(),(int)child_pid); pid=wait(&status); printf("Child Process finished:PID=%d\n",child_pid); if(WIFEXITED(status)) printf("ChildProcess exited with code %d\n",WEXITSTATUS(status)); else printf("Child Process Terminated Abnormally\n"); break; } return 0;}
二、进程间的通信
1、信号
定义在头文件<signal.h>中
用kill -l 可以查看所有信号。
可以通过signal()或者sigaction()函数设定某个信号的处理方法。
void (*signal(int signum,void(*handler)(int)))(int);
int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);
第一个参数为信号值,可以为除SIGKILL SIGSTOP外的信号;第二个参数是指向结构的一个实例指针,指定对特定信号的处理,可以为空;第三个参数指向的对象用来保存对相应信号的处理,可以设定为NULL。
信号的使用主要步骤为:安装信号,实现信号,处理函数,发送信号。信号的生命周期从信号发送开始,到相应的处理函数结束。
#include<signal.h>#include<unistd.h>#include<stdio.h>#include<sys/time.h>void SignalHandle(int signal) //信号处理函数{ switch (signal) { case SIGHUP: printf("Catch Signal: SIGHUP(%d)\n",signal); break; case SIGINT: printf("Catch Signal:SIGINT(%d)\n",signal); break; case SIGQUIT: printf("Catch Signal:SIGQUIT(%d)\n",signal); break ; case SIGALRM: printf("Catch Signal :SIGALRM(%d)\n",signal); break; default: printf("UNknow Signal:%d",signal); break; }}int main(){ int sec_delay=5; printf("Current Process Id:%d\n",(int)getpid()); signal(SIGQUIT,SignalHandle); signal(SIGALRM,SignalHandle); alarm(sec_delay); //5s后输出 while(1) pause(); return 0;}
2、命名管道命令
管道一端顺序写入数据,另一端顺序读数据,数据只能向一个方向流动,所以要双方通信要两个管道。
命名管道利用建立系统特殊文件,以FIFO的文件形式存在,一般使用mkfifo()函数创建相应的文件。
int mkfifo(const char* pathname,mode_t mode);第一个参数是文件路径,mode是打开方式。
#include<unistd.h>#include<fcntl.h>#include<limits.h>#include<sys/types.h>#include<sys/stat.h>#include<stdlib.h>#include<stdio.h>#include<string.h>#define FIFO_HANDLE_NAME "/tmp/fifo_hanfle" #define FIFO_CLIENT_NAME "/tmp/fifo_client_%d "struct ps_fifo_struct{ pid_t pid; char str[64];};int main(){ int fifo_handle,fifo_client; struct ps_fifo_struct ps_fifo; char client_fifo_name[64]; fifo_handle=open(FIFO_HANDLE_NAME,O_WRONLY); if(fifo_handle==-1) { fprintf(stderr,"Open handle fifo failed\n"); exit(EXIT_FAILURE); } ps_fifo.pid=getpid(); memset(client_fifo_name,0,64); sprintf(client_fifo_name,FIFO_CLIENT_NAME,ps_fifo.pid); if(access(client_fifo_name,F_OK)==-1){ if(mkfifo(client_fifo_name,0777)!=0){ fprintf(stderr,"Could not create fifo %s\n",client_fifo_name); exit(EXIT_FAILURE); } } sprintf(ps_fifo.str,"hi,I'm %d",ps_fifo.pid); printf("%d sent:\'%s'.\n",ps_fifo.pid,ps_fifo.str); write(fifo_handle,&ps_fifo,sizeof(ps_fifo)); fifo_client=open(client_fifo_name,O_RDONLY); if(fifo_client!=-1){ if(read(fifo_client,&ps_fifo,sizeof(ps_fifo))>0) printf("received from %d:%s\n",ps_fifo.pid,ps_fifo.str); close(fifo_client); } close(fifo_handle); unlink(client_fifo_name); exit(EXIT_SUCCESS);}
#include<unistd.h>#include<fcntl.h>#include<limits.h>#include<sys/types.h>#include<sys/stat.h>#include<stdlib.h>#include<stdio.h>#include<string.h>#define FIFO_HANDLE_NAME "/tmp/fifo_hanfle" //fifo 文件#define FIFO_CLIENT_NAME "/tmp/fifo_client_%d " struct ps_fifo_struct{ pid_t pid; //进程的PID char str[64]; //对应的FIFO文件名};int main(){ int fifo_handle,fifo_client; char client_fifo_name[64]; char answer_str[64]; struct ps_fifo_struct ps_fifo; int read_len;//如果文件不存在且建立文件失败 if(access(FIFO_HANDLE_NAME,F_OK)==-1) { if(mkfifo(FIFO_HANDLE_NAME,0777)==-1){ fprintf(stderr,"Could not create fifo %s\n",FIFO_CLIENT_NAME); exit(EXIT_FAILURE); } } fifo_handle=open(FIFO_HANDLE_NAME,O_RDONLY);//打开处理的fifo文件 if(fifo_handle==-1) { fprintf(stderr,"Open handle fifo failed\n"); exit(EXIT_FAILURE); } while(read_len>0) { read_len=read(fifo_handle,&ps_fifo,sizeof(ps_fifo)); //读取文件里的内容 memset(answer_str,0,64); if(read_len>0){ sprintf(answer_str,"hi,%d,Ihavereceivedhestring:'%s'.",ps_fifo.pid,ps_fifo.str); printf("received from %d:%s\n",ps_fifo.pid,ps_fifo.str); memset(client_fifo_name,0,64); sprintf(client_fifo_name,FIFO_CLIENT_NAME,ps_fifo.pid); fifo_client=open(client_fifo_name,O_WRONLY); //打开对应的另一个进程的文件 ps_fifo.pid=getpid(); sprintf(ps_fifo.str,answer_str); if(fifo_client!=-1){ write(fifo_client,&ps_fifo,sizeof(ps_fifo)); //写入这个文件当中 close(fifo_client); } } } close(fifo_handle); unlink(FIFO_HANDLE_NAME); exit(EXIT_SUCCESS);}
3、信号量
主要用来控制多个进程对临界资源的互斥访问,信号量是一种进程的同步机制。
key_t ftok(char *pathname,char proj);int semget(key_t key,int nsems,int semflg);int semop(int semid,struct sembuf *spos,int nspos);int semctl(int semid,int semnum,int cmd,union semun arg);ftok()函数创建一个关键字,成功时返回一个键值,失败时返回-1.
semget()函数创建一个新的信号量或者取得一个现有的信号量。
nsems表明创建信号量的个数。
semflg设置信号量的访问权限标志,调用成功返回信号量的ID,失败返回-1.
semop用于改变信号量键值,semid是信号标志,spos是表明进行什么操作的结构指针,nspos表示数组元素的个数。
semctl()对信号量进行一系列的控制,SETVAL 设置信号量的值,IPC_RMID删除信号量。
#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/sem.h>#define SEM_PATHNAME "/tmp/my_sem"union semun{ int val; struct semid_ds *buf; unsigned short *array; struct semfifo *__buf; void *__pad;};int main(int argc,char *argv[]){ int sem_id,sem_key; union semun arg_ctl; struct sembuf sem_bufinfo; int option_get=IPC_CREAT|IPC_EXCL|0666; sem_key=ftok(SEM_PATHNAME,'X'); sem_id=semget(sem_key,1,option_get); printf("semaphore id=%d.\n",sem_id); arg_ctl.val=1; if(-1==semctl(sem_id,0,SETVAL,arg_ctl)) perror("semctl error"); printf("value of semaphore at index 0 is %d.\n",semctl(sem_id,0,GETVAL,arg_ctl)); sem_bufinfo.sem_num=0; sem_bufinfo.sem_op=-1; sem_bufinfo.sem_flg=IPC_NOWAIT; semop(sem_id,&sem_bufinfo,1); printf("value of semaphore at index 0 is %d \n",semctl(sem_id,0,GETVAL,arg_ctl)); return 0;}
4、信号队列
消息队列是将消息按队列的方式组成链表。
int msgget(key_t key,int msgflg);int msgsnd(int msqid,const void *msgptr,int msgsz,int msgflg);int msgrcv(int msqit,void *msgptr,int msgsz,long msgtyp,int msgflg);int msgctl(int msqid,int cmd,struct msqid_ds *buf);
#include<sys/types.h>#include<sys/msg.h>#include<unistd.h>#include<stdlib.h>#include<stdio.h>int main(){ int msg_id,msg_flags; int reval; char send_msg[64]; msg_flags=IPC_CREAT|0666; msg_id=msgget((key_t)456,msg_flags); //建立消息队列 sprintf(send_msg,"Hi,I am%d.",getpid()); reval=msgsnd(msg_id,send_msg,sizeof(send_msg),0); //将消息发送到队列中 return 0;}#include<sys/types.h>#include<sys/msg.h>#include<unistd.h>#include<stdlib.h>#include<stdio.h>int main(){ int msg_id,msg_flags; int reval; char send_msg[64]; msg_flags=IPC_CREAT|0666; msg_id=msgget((key_t)456,msg_flags); //建立消息队列 reval=msgrcv(msg_id,send_msg,64,0,0); printf("Received msg:%s\n",send_msg); reval=msgctl(msg_id,IPC_RMID,0); return 0;}5、共享内存
在linux中只要吧共享内存段连接到进程的地址空间中,这个进程就可以访问共享内存中的地址。
1、int shmget(key_t key,int shmsz,int shmflg);
该函数分配一块共享内存,shmsz指明共享内存的大小,shmflg的设置和其他函数中的类似。
如果调用成功则返回共享内存的ID,否则-1;
2、void *shmat(int shmid,const void *shmaddr,int shmflg);
该函数用老连接共享内存和地址空间
3、int shmdt(const void *shmaddr);
用来解除进程和共享内存的关联。
4、int shmctl(int shmid,int cmd,struct shmid_ds *buf);
实现对共享内存区域的操作控制。
- linux 进程编程:进程终止
- linux 进程编程:进程创建
- Linux进程编程笔记
- linux多进程编程
- linux 进程编程
- linux 多进程编程
- Linux进程编程
- linux进程编程
- Linux进程编程实例
- Linux进程编程实例
- Linux进程编程基本概念
- Linux环境编程--进程
- linux进程编程
- Linux编程2: 进程
- linux进程编程
- Linux进程编程实例
- Linux多进程编程
- linux 守护进程编程
- AVL的c++详解——删除
- 使用struts2的token机制和cookie来防止表单重复提交
- D001-开发工具-VS Code
- SAP启用检查双重Invoice功能
- addr2line
- linux 进程编程
- 第十章——内部排序
- 递归调用中使用全局变量或者函数参数
- stl中的vector(向量)
- socket,accept函数解析
- ECDH and ECDSA(ECC椭圆曲线算法3)
- 【MyBatis】Myeclipse中Mybatis Generator插件的安装
- Django模型层Meta内部类详解
- C++学习(31)