linux--进程(7)

    xiaoxiao2026-10-09  0

    进程

    进程和程序:进程是动态的,内存调度;程序是静态的

    进程(操作系统中分配的去实现一个功能的一块资源)创建进程——fork和vfork区别 fork:子进程拷贝父进程的数据段,父、子进程的执行次序不确定 vfork:子进程与父进程共享数据段,子进程先运行、父进程后运行三种创建进程方式流程: fork() 父进程(pid为非零数)–fork–创建子进程(pid=0)vfork() 父进程(pid为非零数)–vfork–创建子进程(pid=0)exec() 进程创建新进程,新进程覆盖取代旧的进程,pid一样,无数据返回 (fork是建立副本)

    基本函数:

    fork:用于创建一个新进程;exit:终止进程;exec:执行一个应用程序;wait:将父进程挂起,等待子进程终止;getpid:获取当前进程的进程ID;nice:改变进程优先级。

    守护进程

    流程: 创建子进程,父进程退出-> 在子进程中创建新会话->改变当前目录为根目录->重设文件权限掩码->关闭文件描述符->守护进程退出处理 /* 流程.c ---了解即可 */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<fcntl.h> #include<sys/types.h> #include<unistd.h> #include<sys/wait.h> #define MAXFILE 65535 void sigterm_handler(int arg); volatile sig_atomic_t _running = 1; int main(int argc, char **argv) { pid_t pc,pid; int i,fd,len,flag = 1; 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); } pid = setsid(); //第二步 if (pid < 0){ perror("setsid error"); } chdir("/"); //第三步 umask(0); //第四步 for(i=0;i<MAXFILE;i++){ //第五步 close(i); } signal(SIGTERM, sigterm_handler);/*第六步*/ while( _running ){ if( flag ==1 && (fd=open("/tmp/daemon.log",O_CREAT|O_WRONLY|O_APPEND,0600))<0){ perror("open"); flag=0; exit(1); } write(fd,buf,len); close(fd); usleep(10*1000); //10毫秒 } return 0; } void sigterm_handler(int arg) { _running = 0; }

    进程间的通信(IPC)

    六种通信方式 管道(Pipe)及有名管道(named pipe) 信号(Signal) 报文(Message)队列(消息队列) 共享内存 信号量(semaphore) 套接口(Socket)

    管道(Pipe) (绑定读写段,单向管道通信) 特点: 1.单双工(只向一个方式传递) 2.只适用于亲缘进程 3.数据读取类似管道排水,先进先出 一般用fd[0]和fd[1]描述管道两端: fd[0](管道读端)——————————fd[1](管道写端) 读规则: 1.写端不存在,即返回读出字节0 2.写端存在,读数据>管道内数据,返回管道内数据;读数据<管道内数据,返回读数据。 写规则: 1.超过最大管道会阻塞有名管道(named pipe或FIFO) 特点:可以不是亲缘关系的进程通信 /* 管道通信(父进程写,子进程读) */ #include <unistd.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <stdlib.h> main() { int pipe_fd[2]; pid_t pid; char r_buf[100]; char w_buf[4]; char* p_wbuf; int r_num; memset(r_buf,0,sizeof(r_buf)); memset(w_buf,0,sizeof(r_buf)); p_wbuf=w_buf; //创建管道,判断管道正常 if(pipe(pipe_fd)<0) { printf("pipe create error\n"); return -1; } //子程序读,关闭写端 if((pid=fork())==0) { printf("\n"); close(pipe_fd[1]); sleep(3);//确保父进程关闭写端 r_num=read(pipe_fd[0],r_buf,100); printf( "read num is %d the data read from the pipe is %d\n",r_num,atoi(r_buf)); //atoi()把字符串变为int型 close(pipe_fd[0]); exit(0); } //父程序写,关闭读端 else if(pid>0) { close(pipe_fd[0]);//read strcpy(w_buf,"111"); if(write(pipe_fd[1],w_buf,4)!=-1) printf("parent write over\n"); close(pipe_fd[1]);//write printf("parent close fd[1] over\n"); sleep(10); } return 0; } 信号 (安装信号,然后传送信号) 信号是进程间通信机制中唯一的异步通信机制 (同步通信:建立同步,一起工作;异步通信:发送端随意发送,接收端时刻准备接) /***基本函数****/ kill() 杀死信号 raise() 向进程本身发送信号 signal 安装信号 sigaction 新的安装信号,配合sigqueue(发送信号系统调用)使用 alarm() setitimer() abort() 向进程发送SIGABORT信号

    队列(消息队列) (消息队列就是一个消息链表,有读写权限,就可以操作它)

    信号量 (信号量是控制多个进程对共享内存的计数器)

    特点: 控制多个进程对共享内存的计数器,当一个进程在操作内存时,其他不能基本函数 semget() 建立新的信号量对象或者获取已有对象的标识符 semop() 改变信号量对象中各个信号量的状态 semctl() 直接对信号量对象进行控制 /*semtool 的命令行语法 建立信号量对象: semtool c (number of semaphores in set) 锁定信号量: semtool l (semaphore number to lock) 解开信号量的锁定 semtool u (semaphore number to unlock) 改变信号量的权限 semtool m (mode) 删除信号量对象 semtool d semtool 的使用举例 semtool c 5 semtool l semtool u semtool m 660 semtool d */ 共享内存(最快的IPC方式) (同一物理内存被映射到进程A、B各自的地址空间) 两个不同进程A、B共享内存 基本函数 mmap() 使得进程之间通过映射同一个普通文件实现共享内存 munmap() 进程地址空间中解除一个映射关系 msync() 实现磁盘上文件内容与共享内存区的内容一致系统V共享内存 基本函数 shmget() 获得共享内存区域的ID,如果不存在指定的共享区域就创建相应的区域 shmat() 共享内存区域映射到调用进程的地址空间中去,这样,进程就可以方便地对共享区域进行访问操作 shmdt() 调用用来解除进程对共享内存区域的映射 shmctl() 实现对共享内存区域的控制操作 - /************1.对文件共享内存操作***********************/ /*写入*/ #include <sys/mman.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> main(int argc, char** argv) { int fd,i; char *p_map; char temp; fd=open("m.txt",O_CREAT|O_RDWR|O_TRUNC,00777);//1.文件名称,argv[1]代表自己输入;2.打开方式;3.文件权限 lseek(fd,150,SEEK_SET); write(fd,"",1);//偏移150,最后一个位置设置为" " //映射文件(1.映射地址 2.映射大小 3.操作方式 4.映射方式5.文件符6.从0开始映射) p_map = (char *)mmap( NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0 ); close( fd ); strcpy(p_map, "abcd"); //解除映射 munmap( p_map, 100 ); printf( "umap ok \n" ); } /*读出*/ #include <sys/mman.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char** argv) { int fd,i; char *p_map; fd=open( "m.txt",O_CREAT|O_RDWR,00777 ); p_map = (char*)mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); close(fd); printf( "str: %s\n",p_map); munmap( p_map,100 ); return 0; } /*执行方式:gcc xxx1.c -o 11 *gcc xxx2.c -o 22 *./11 *./22 */ /************2.IPC共享内存区域***********************/ /*写(有问题)*/ #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char** argv) { int shm_id; key_t key; char *p_map; char *name = "n.txt"; //获取一个指定的ID key = ftok(name,'a'); //用来获得共享内存区域的ID,如果不存在指定的共享区域就创建相应的区域 //1.2.大小3.处理方式 shm_id = shmget(key,5,IPC_CREAT); //把共享内存区域映射到调用进程的地址空间中去,这样,进程就可以方便地对共享区域进行访问操作 p_map = (char *)shmat(shm_id,NULL,0); strcpy(p_map, "a"); //shmdt()调用用来解除进程对共享内存区域的映射 shmdt(p_map); return 0; } /*读(有问题)*/ #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <unistd.h> #include <stdio.h> int main(int argc, char** argv) { int shm_id,i; key_t key; char *p_map; char* name = "n.txt"; key = ftok(name,0); if(key == -1) perror("ftok error"); shm_id = shmget(key,5,IPC_CREAT); if(shm_id == -1) { perror("shmget error"); return; } p_map = (char*)shmat(shm_id,NULL,0); //printf("%s", p_map); if(shmdt(p_map) == -1) perror(" detach error "); return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-1312772.html
    最新回复(0)