Skip to content

进程

1.查进程

ps命令查找与进程相关的PID号:

ps a 显示现行终端机下的所有程序,包括其他用户的程序。

ps -A 显示所有程序。

ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。

ps -e 此参数的效果和指定"A"参数相同。

ps e 列出程序时,显示每个程序所使用的环境变量。

ps f 用ASCII字符显示树状结构,表达程序间的相互关系。

ps -H 显示树状结构,表示程序间的相互关系。

ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。

ps s 采用程序信号的格式显示程序状况。

ps S 列出程序时,包括已中断的子程序资料。

ps -t<终端机编号> 指定终端机编号,并列出属于该终端机的程序的状况。

ps u 以用户为主的格式来显示程序状况。

ps x 显示所有程序,不以终端机来区分。

2.杀进程

使用kill命令结束进程:kill xxx(PID/进程的名字)

3.exce()族函数的使用

4.fork

c
   #include <sys/types.h>
   #include <unistd.h>

   pid_t fork(void);

fork() 函数是用于创建一个新的进程的系统调用。调用 fork() 后,会产生两个几乎完全相同的进程,一个是父进程,另一个是子进程。这两个进程在执行时拥有相同的程序代码、数据以及状态。

fork() 调用之后,父子进程会有不同的返回值:

在父进程中,fork() 返回子进程的PID(Process ID),也就是新创建子进程的标识符。

在子进程中,fork() 返回0。

此外,在父子进程中还可以通过获取PPID(Parent Process ID)来获得对方的信息。具体来说:

在父进程中,获取到的PPID就是它自己的PID。

在子进程中,获取到的PPID就是它父进程的PID。

image-20231207082911361

image-20231207090528648

image-20231207090619824

5.sleep

其中,Sleep()里面的单位,是以毫秒为单位,所以如果想让函数滞留1秒的话,应是Sleep(1000);

6.wait

‘Z’是僵尸进程

c
   #include <sys/types.h>
   #include <sys/wait.h>

父对子负责,子进程结束后,先杀死子进程,再杀死父进程

进程的链接/通信

通过通道

未命名通道 - pipe

头文件

c
#include <unistd.h>

参数

c
int pipe(int filedes[2]);

描述:

pipe 函数用于创建一个无名管道,它返回两个文件描述符,分别对应于管道的读端和写端。数据写入管道的写端可以被从管道的读端读取。通常,一个进程创建管道后,调用 fork 创建子进程,子进程关闭写端,父进程关闭读端,这样就可以在它们之间实现通信。

两个文件描述符

filedes[0]子

filedes[1]父

例子

c
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#define BUFFER 20
#define NUMBER 20
int main(){

        int  fd[2];//fd[0]读fd[1]写
        pid_t pid;
        char buffer[BUFFER];
        char number[NUMBER];
        if(pipe(fd)){
                perror("pipe error:");
                exit(0);
        }
        pid = fork();//先pipe后fork 因为fork会创建一个一样进程,这样就是两个进程了
        if(pid == 0){
                close(fd[0]);
                scanf("%s",buffer);
                write(fd[1],buffer,BUFFER);
                exit(0);
                close(fd[1]);

        }
        else{//父接收
                close(fd[1]);
                read(fd[0],number,NUMBER);
                printf("输出结果:%s\n",number);
                close(fd[0]);
        }


        return 0;

}

命名通道 - mkfifo

头文件

c
#include <sys/types.h>
#include <sys/stat.h>

参数

c
int mkfifo(const char *pathname, mode_t mode);

描述:

mkfifo 函数用于创建一个命名管道,可以通过文件系统中的路径名进行访问。它返回 0 表示成功,-1 表示失败。通常,一个进程通过调用 open 打开一个命名管道文件,然后进行读写操作。

例子

c
#include <sys/types.h>
#include <sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>

#define BUFFER 20
int main(){
        pid_t pid;
        int fd;
        char buffer[BUFFER];

        mkfifo("datafile",07777);//可读可写可执行
        pid = fork();
        if(pid == 0){
                char s[] = "helloworld\n";
                fd = open("datafile",O_WRONLY);
                write(fd,s,sizeof(s));

                exit(0);
        }
        else{
                fd = open("datafile",O_RDONLY);
                read(fd,buffer,sizeof(buffer));
                printf("输出:%s\n",buffer);
        }
        return 0;

}

消息队列

消息队列是一种进程间通信的机制,用于在不同进程之间传递消息。它是一种先进先出(FIFO)的数据结构,消息发送者将消息放入队列的尾部,而消息接收者则从队列的头部获取消息。消息队列提供了一种松散耦合的通信方式,允许不同的进程在不共享内存的情况下进行通信。

共享内存

共享内存是一种用于进程间通信的机制,允许多个进程访问同一块内存区域。不同于消息队列,共享内存是一种更为直接和高效的通信方式,因为多个进程可以直接读写共享的内存区域,而无需通过中间的消息传递。

Domain Socket

线程主要讲这个

线程

进程是由线程组成的(至少一个)

pthread_create

c
#include <pthread.h>   
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

(1)tidp:事先创建好的pthread_t类型的参数。成功时tidp指向的内存单元被设置为新创建线程的线程ID。

(2)attr:用于定制各种不同的线程属性。通常直接设为NULL。

(3)start_rtn:新创建线程从此函数开始运行。无参数是arg设为NULL即可。

(4)arg:start_rtn函数的参数。无参数时设为NULL即可。有参数时输入参数的地址。当多于一个参数时应当使用结构体传入

返回值 成功的话 -> 0

pthread_exit

c
#include <pthread.h>
void pthread_exit(void *retval);

只适合终止自己的线程

pthread_cancel

c
#include <pthread.h>

int pthread_cancel(pthread_t thread);

终止其他的线程

return 0; 也可以终止

pthread_join

等待

c
   #include <pthread.h>
   int pthread_join(pthread_t thread, void **retval);

例子

c
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>

#define LEFT 3000000
#define RIGHT 3000200
static void * thr_prime(void *p);
int main(){
        pthread_t tid[RIGHT-LEFT+1];
        int i,err;
        for(i = LEFT;i<=RIGHT;i++){
                err = pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)&i);
                if(err!=0){
                        fprintf(stderr,"线程创建失败");
                        exit(0);
                }
        }
        for(i = LEFT;i<=RIGHT;i++){
                pthread_join(tid[i-LEFT],NULL);
        }
}
static void * thr_prime(void *p){
        int j;
        int mark = 1;
//      int i =(int)p;注意解决这个问题
        int i = *((int *)p);
        for(j= 2;j<=i/2;j++){
                if(i%j==0){
                        mark = 0;
                        break;
                }
        }
        if(mark){
                printf("%d\n",i);
        }
        pthread_exit(NULL);
}
  1. int i = (int)p;

    这是一种直接的指针到整数的转换,将指针 p 直接转换为整数类型。这种转换可能导致信息丢失,因为指针通常比 int 类型的整数更长。这种转换在某些情况下可能会导致错误,因为指针可能表示的是一个内存地址,而将其强制转换为整数可能不会产生有意义的结果。

  2. int i = \*((int \*)p);

    这是一种间接的指针到整数的转换。首先,将 p 强制转换为 int * 类型的指针,然后使用解引用运算符 * 获取指针指向的值。这样的操作通常用于从指针所指向的内存位置读取数据,而不是将指针本身转换为整数。

Domain Socket

域套接字,也称为Unix套接字,提供了同一台主机上的进程进行通信的一种方法。与常规(Internet)套接字不同,域套接字存在于文件系统中,通过文件路径而不是IP地址和端口进行标识。

以下是在Linux中使用域套接字的基本概述:

  1. 创建域套接字: 要创建域套接字,可以使用socket()系统调用,指定AF_UNIX地址族:

    cCopy code
    int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
  2. 为套接字绑定名称: 创建套接字后,需要为其绑定一个名称。名称是文件系统中的文件路径。这可以通过bind()系统调用完成:

    cCopy codestruct sockaddr_un addr;
    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path, "/tmp/my_socket");
    
    bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
  3. 监听连接(对于SOCK_STREAM): 如果使用流式套接字(SOCK_STREAM),可以监听传入的连接:

    cCopy code
    listen(sockfd, backlog);
  4. 接受连接(对于SOCK_STREAM): 使用accept()系统调用接受传入连接:

    cCopy code
    int newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
  5. 发送和接收数据: 对于流式套接字,可以使用send()recv()发送和接收数据。对于数据报套接字(SOCK_DGRAM),可以使用sendto()recvfrom()

  6. 关闭套接字: 最后,在完成后关闭套接字:

    cCopy code
    close(sockfd);
  7. 清理: 如果程序退出或需要清理套接字文件,可以使用unlink()从文件系统中删除套接字文件:

    cCopy code
    unlink("/tmp/my_socket");

Released under the MIT License.