Resumen de los puntos de conocimiento de programación de Linux

  • Makefile

1.1 Estructura:

objetivos: requisitos previos

  dominio

1.2 compilación gcc: -g, -o, -c, -D, -w, -W, -Wall, -O3

-c: los archivos fuente se compilan y ensamblan, pero no se vinculan

Ejemplo:

gcc -c prueba.cpp -o prueba

-c seguido de varios archivos fuente

      Cuando -c va seguido de varios archivos de origen, se generará un archivo .o para cada archivo de origen, pero -o no se puede usar en este momento .

Enlace de referencia: Introducción a las opciones de compilación de gcc -o y -c_gcc -o_chengqiuming's Blog-CSDN Blog

1.3 Variables de automatización

variable de automatización

ilustrar

ps

Indica el archivo de objeto

ps

Cuando el archivo de destino es un archivo de biblioteca estática, representa un nombre de miembro de la biblioteca estática.

$<

Indica el primer archivo dependiente.

$^

Representa todos los archivos dependientes.

ps

Una lista de todos los archivos dependientes más nuevos que el archivo de destino.

$+

Como "$^", pero conserva las ocurrencias duplicadas de archivos dependientes. Se utiliza principalmente en la ocasión de referencia cruzada de la biblioteca cuando el programa está vinculado.

ps

En reglas de patrones y reglas de patrones estáticos, significa "tallo". El "tallo" es la parte representada por el "%" en el patrón de destino (cuando un directorio está presente en el nombre del archivo,

prueba: prueba.o prueba1.o prueba2.o

         gcc -o $@ $^

prueba.o:prueba.c prueba.h

         gcc -o $@ $<

prueba1.o:prueba1.c prueba1.h

         gcc -o $@ $<

prueba2.o:prueba2.c prueba2.h

         gcc -o $@ $<

Agregar los caracteres "D" o "F" a estas variables en GNU crea una serie de variables de automatización de variantes que pueden operar en los nombres de los archivos.

D representa la parte del directorio y F representa la parte del archivo. Tales como: $(@D), $(@F)

1.4 Búsqueda de archivos de objetos

4.1 VPATH

VPATH := src coche

prueba:prueba.o

    gcc -o $@ $^

Primero se buscan los archivos en el directorio src y luego se buscan los archivos en el directorio car.

4.2 vpath

vpath test.c src coche

Busque archivos test.c en dos rutas

1.5 objetivos falsos

limpio:

    rm -rf *.o prueba

dos, la concha

Enlace de referencia: https://www.jianshu.com/p/74e8739ddc01

script de shell 2.1,

#!/bin/bash

echo "¡HolaMundo!"

2.2 Declaración de control de flujo

si – entonces – si no – fi

si no

si elif fi

en bucle

mientras declaración

hasta bucle (opuesto a la condición while)

caso... esac

-eq/-ne/-gt/-ge/-lt/le

mayor o igual mayor o igual

-e verdadero si el archivo existe

-r True si el archivo existe y es legible

-w True si el archivo existe y se puede escribir

-x True si el archivo existe y es ejecutable

-s True si el archivo existe y tiene al menos un carácter

-d verdadero si el archivo es un directorio

-f verdadero si el archivo existe y es un archivo normal

-c verdadero si el archivo existe y es un archivo especial de caracteres

-b True si el archivo existe y es un archivo especial de bloque

2.3 Funciones

Ejemplo:

#!/bin/bash

función vecesDiversión(){

    echo " Esta función multiplicará dos números "

    echo " Por favor ingrese el primer número "

    leer num1

    echo " Por favor ingrese el segundo número "

    leer num2

    devolver $(( ${num1} * ${num2} ))

}

tiemposdivertidos

echo -n " ​​¿ El valor de multiplicación de los dos números ingresados ​​es $?"

3. Puntero

En comparación con otros lenguajes de programación de alto nivel, el lenguaje C puede operar el hardware de la computadora de manera más eficiente, y las instrucciones de operación del hardware de la computadora dependen en gran medida de las direcciones.

Los punteros proporcionan una forma de operar en las direcciones, por lo tanto, el uso de punteros puede permitir que el lenguaje C opere de manera más eficiente en el hardware subyacente de la computadora. Además, las matrices se pueden manipular de manera más conveniente a través de punteros. En cierto sentido, se puede decir que el puntero es la esencia del lenguaje C.

3.1 Memoria y dirección

Enlace de referencia: http://c.biancheng.net/c/pointer/

(1) &: Obtener dirección variable

(2) Definición de variable de puntero: como int *p;

http://c.biancheng.net/uploads/allimg/180903/2-1PZ3145331D9.jpg

(3) puntero "salvaje"

int *pi,a; //pi no está inicializado, no tiene puntero legal y es un puntero "salvaje"

*pi=3; // ¡ Error de tiempo de ejecución! La operación de almacenamiento no se puede realizar en el espacio señalado por el puntero "comodín". Esta declaración intenta almacenar 3 en el espacio aleatorio al que apunta el puntero pi "salvaje" y se producirá un error de tiempo de ejecución

(4) Punteros y matrices

Puntero de matriz: ejemplo int (*p)[5]; puede representar una matriz bidimensional

#definir M 3

#definir N 4

int a[M][N],i,j;

int (*p)[N]=a; // equivalente a dos sentencias int (*p)[N] ; p=a;

Matriz de punteros: ejemplo int * a[5];

int a0,a1,a2,a3,a4;

a[0]=&a0;

a[1]=&a1;

...

a[4]=&a4;

3.2 Punteros de función

Enlace de referencia: https://blog.csdn.net/Jacky_Feng/article/details/108953519

(1) Definición de puntero de función

Si se define una función en el programa, al compilar, el compilador asignará una sección de espacio de almacenamiento para el código de la función, y la dirección inicial de este espacio (también conocida como la dirección de entrada) se denomina puntero de esta función.

Ejemplo:

int func(int a,int b);// declaración de función

int (*p) (int , int );// Defina una lista de parámetros como dos variables de tipo int , y el tipo de valor devuelto es un puntero de función p de tipo int

p=func ; // El puntero de función p apunta a la dirección inicial de la función func

(2) Aplicación de punteros de función

Llame a la función a la que apunta el puntero de función p

( *p ) (3, 5);

3.3 Función de devolución de llamada

El programa pasa el puntero de función de esta función a otras funciones a través de parámetros, y llamar a este puntero de función en esa función es equivalente a llamar a esta función.Tal proceso se llama devolución de llamada, y la función llamada se llama función de devolución de llamada.

Ejemplo:

#incluir <iostream>

utilizando el espacio de nombres estándar;

 // 1. Definir la función de devolución de llamada

impresión vacía (int n)

{

      para (int i = 0; i < n; i++) {

             cout << "hola mundo" << endl;

      }

}

// 2. Definir el prototipo de función de devolución de llamada (puntero de función)

typedef void (*CallbackFun)(int);

 // 3. Definir la función de devolución de llamada de registro

void registCallback(CallbackFun callback,int n)

{

      devolución de llamada (n);

}

 int principal()

{

    // 4. Pase el puntero de la función de impresión como un parámetro a la función de registro registerCallback para llamar a la devolución de llamada , es decir, se ejecuta la función de impresión .

      registrarseCallback(imprimir, 10);

}

4. Multihilo y multiprocesamiento

Para sistemas roscados:

(1) Un proceso es una unidad independiente de asignación de recursos

(2) Thread es una unidad independiente de programación de recursos

Para sistemas sin rosca:

(1) Un proceso es una unidad independiente de programación y asignación de recursos

4.1 Métodos de comunicación entre procesos y sus ventajas y desventajas

Tubería (TUBO )

(1) Tubería conocida: un método de comunicación semidúplex que permite la comunicación entre procesos no relacionados.

①Ventajas: Se puede realizar la comunicación entre procesos de cualquier relación.

②Desventajas: a. Almacenamiento a largo plazo en el sistema, el uso inadecuado es propenso a errores; b. Búfer limitado.

(2) Tubería sin nombre: un método de comunicación semidúplex que solo se puede usar entre procesos con parentesco (proceso padre-hijo).

①Ventajas: Simple y conveniente.

② Desventajas: a. Limitado a la comunicación unidireccional, b. Solo se puede crear entre su proceso y sus procesos relacionados, c. El búfer es limitado.

Semáforo (Semaphore): Un contador que se puede utilizar para controlar el acceso a los recursos compartidos por varios subprocesos.

  • Pros: Puede sincronizar procesos.

② Desventajas: semáforo limitado.

Signal (Señal ): Un método de comunicación más complejo que se utiliza para notificar al proceso de recepción que se ha producido un evento.

Message Queue (Cola de Mensajes ): Es una lista enlazada de mensajes, almacenados en el kernel e identificados por un identificador de cola de mensajes.

  • Ventajas: puede realizar la comunicación entre cualquier proceso y realizar la sincronización entre el envío y la recepción de mensajes a través de la función de llamada al sistema, sin considerar el problema de sincronización, lo cual es conveniente.

② Desventajas: La copia de información requiere tiempo adicional de CPU, lo que no es adecuado para ocasiones con gran cantidad de información u operaciones frecuentes.

Memoria compartida (Shared Memory ): mapea una sección de memoria a la que otros procesos pueden acceder. Esta memoria compartida es creada por un proceso, pero múltiples procesos pueden acceder a ella.

  • Ventajas: sin necesidad de copiar, rápido, gran cantidad de información.

② Desventajas: a. La comunicación se logra conectando directamente el búfer de espacio compartido al espacio de direcciones virtuales del proceso, por lo que la sincronización de las operaciones de lectura y escritura entre procesos; b. Usando el búfer de memoria para intercambiar información directamente, la entidad del memoria Existe en la computadora y solo puede ser compartida por muchos procesos en el mismo sistema informático, lo cual es un inconveniente para la comunicación en red.

Socket (Socket ): se puede utilizar para la comunicación de procesos entre diferentes computadoras

①Ventajas:

a. Los datos de transmisión están a nivel de byte, los datos de transmisión se pueden personalizar, el volumen de datos es pequeño y la eficiencia es alta;

B. Corto tiempo de transmisión de datos y alto rendimiento;

C. Adecuado para la interacción de información en tiempo real entre el cliente y el servidor;

D. Se puede cifrar y la seguridad de los datos es fuerte;

② Desventajas: los datos transmitidos deben analizarse y convertirse en datos de nivel de aplicación.

4.2 Métodos de comunicación entre hilos

4.2.1 Mecanismo de bloqueo

Incluye mutex/cantidad (mutex), bloqueo de lector-escritor (bloqueo de lector-escritor), bloqueo de giro (bloqueo de giro), variable de condición (condición)

  1. Mutex/Volume (mutex): proporciona métodos para evitar que las estructuras de datos se modifiquen simultáneamente de manera exclusiva.

El mecanismo mutex incluye principalmente las siguientes funciones básicas:

  1. Inicialización de exclusión mutua: pthread_mutex_init()
  2. Bloqueo mutex: pthread_mutex_lock()
  3. Bloqueo de juicio mutex: pthread_mutex_trylock()
  4. Bloqueo mutex: pthread_mutex_unlock()
  5. Eliminar mutex: pthread_mutex_destroy()
  1. Bloqueo de lector-escritor (reader-writer lock): permite que varios subprocesos lean datos compartidos al mismo tiempo, mientras que la operación de escritura se excluye mutuamente.

El mecanismo de bloqueo de lectura y escritura incluye principalmente las siguientes funciones básicas:

  1. int pthread_rwlock_init(pthread_rwlock_t * rwlock, const pthread_rwlockattr_t * attr);
  2. int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
  3. int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
  4. int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
  5. int pthread_mutex_timedrdlock(pthread_rwlock_t * rwlock,const struct timespec * tsptr);
  6. int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
  7. int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
  8. int pthread_mutex_timedwrlock(pthread_rwlock_t * rwlock,const struct timespec * tsptr);
  9. int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
  1. Un bloqueo de giro (spin lock) es similar a un mutex, tanto para proteger los recursos compartidos. El mutex es cuando el recurso está ocupado y el solicitante entra en el estado de suspensión, mientras que el bloqueo giratorio realiza un bucle para verificar si el titular ha liberado el bloqueo.

El mecanismo spinlock incluye principalmente las siguientes funciones básicas:

  1. int pthread_spin_destroy(pthread_spinlock_t *bloqueo);
  2. int pthread_spin_init(pthread_spinlock_t *bloqueo, int pshared);
  3. int pthread_spin_lock(pthread_spinlock_t *bloqueo);
  4. int pthread_spin_trylock(pthread_spinlock_t *bloqueo);
  5. int pthread_spin_unlock(pthread_spinlock_t *bloqueo);
  1. Variable de condición (condición): Un proceso puede bloquearse atómicamente hasta que cierta condición sea verdadera. La prueba de la condición se realiza bajo la protección de un mutex. Las variables de condición siempre se usan con mutexes.

Los semáforos multiproceso incluyen las siguientes funciones básicas.

  1. int sem_init(sem_t *sem, int pshared, int val sin firmar);
  2. int sem_espera(sem_t *sem);
  3. int sem_post(sem_t *sem);
  4. int sem_destory(sem_t *sem);

4.2.2 Mecanismo de semáforo (Semaphore)

(1) Semáforo de hilo sin nombre

(2) Semáforo de subproceso con nombre

Mecanismo de señal (Signal): similar al procesamiento de señales entre procesos

Barrera: una barrera permite que cada subproceso espere hasta que todos los subprocesos cooperantes hayan llegado a un punto determinado y luego continúe la ejecución desde ese punto.

El propósito de la comunicación entre subprocesos es principalmente para la sincronización de subprocesos, por lo que los subprocesos no tienen un mecanismo de comunicación para el intercambio de datos como la comunicación de procesos.

Recursos privados y compartidos entre procesos

Privado: espacio de direcciones, montón, variables globales, pila, registros

Compartido: segmento de código, datos públicos, directorio de procesos, ID de proceso

Recursos privados y compartidos entre hilos

Privado: pila de subprocesos, registros, contador de programa

Compartido: montón, espacio de direcciones, variables globales, variables estáticas

4.3 Comparación, pros y contras y elección entre multiproceso y multihilo

1. Contraste

2. Ventajas y desventajas

3. Seleccione

(1) Subprocesos prioritarios que deben crearse y destruirse con frecuencia

(2) Uso prioritario de subprocesos que requieren una gran cantidad de cálculos

(3) El procesamiento fuertemente relacionado usa subprocesos y el procesamiento débilmente relacionado usa procesos

(4) Puede extenderse para usar procesos para la distribución de múltiples máquinas y usar subprocesos para la distribución de múltiples núcleos

(5) Cuando se cumplan todos los requisitos, utilice el método con el que esté más familiarizado y mejor en

Cinco, programación de red Linux

5.1 TCP

5.1.1 Modelo de red TCP

https://img-blog.csdnimg.cn/2020020517240829.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dmZWFfbGZm,size_16,color_FFFFFF, t_70

Para crear un servidor tcp bajo Linux , hay seis pasos de la siguiente manera:

socket - crea un socket

bind - enlazar host y puerto

listen - establecer el enchufe de escucha

accept - acepta conexiones de clientes y genera nuevos sockets

leer/escribir – enviar y recibir datos

cerrar - cerrar el zócalo

La creación de un cliente se divide principalmente en los siguientes pasos:

socket -- crear un socket

connect -- Conéctese activamente al servidor

escribir/leer: enviar y recibir datos

cerrar - cerrar el zócalo

  1. socket - crea un socket

Prototipo de función: socket int (dominio int, tipo int, protocolo int);

Descripción de parámetros:

dominio: familia de protocolos, especifique la familia de protocolos utilizada para la comunicación; las opciones comunes son las siguientes:

AF_UNIX, AF_LOCAL : Comunicación local , utilizada para la comunicación entre procesos / hilos locales;

AF_INET:Protocolos de Internet IPv4

AF_INET6:Protocolos de Internet IPv6

tipo: tipo de enchufe, las opciones comúnmente utilizadas son las siguientes:

SOCK_STREAM: socket de flujo, correspondiente únicamente a TCP;

SOCK_DGRAM: socket de datagrama, correspondiente únicamente a UDP;

SOCK_RAW: socket crudo (transparente);

protocolo: generalmente complete 0, este parámetro es obligatorio cuando el tipo de tipo es SOCK_RAW.

Valor devuelto: socket (descriptor de archivo) se devuelve en caso de éxito y -1 en caso de error.

  1. bind - enlazar host y puerto

Prototipo de función: int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

Estructura general de la dirección:

estructura sockaddr {

             sa_family_t sa_family; //dirección de la familia

             char en_datos[14];

             }

Estructura de la dirección de Internet:

estructura sockaddr_in {          

             u_short sin_family; // familia de direcciones, AF_INET, 2 bytes

             u_short sin_port; // puerto, 2 bytes

             estructura in_addr sin_addr; // IPV4地址,4 bytes    

             char sin_zero[8]; // 8 bytes sin usar, como relleno

             };

Estructura de la dirección IPv4

// dirección de Internet 

estructura in_addr

{

       in_addr_t s_addr; // dirección de red u32

};

Estructura de dirección del protocolo de comunicación local: se puede utilizar para la comunicación entre procesos

    estructura sockaddr_un

    {

        sa_family_t sun_family; //familia de protocolos

        char sun_path[108]; // ruta del archivo de socket

    }

  1. listen - establecer el enchufe de escucha

Parámetros: sockfd --- descriptor de archivo de socket

        backlog --- monitorear la longitud de la cola

  1. accept - acepta conexiones de clientes y genera nuevos sockets

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

parámetro:

      sockfd --- descriptor de archivo de socket

      addr --- IP del cliente y número de puerto

      addrlen --- longitud de la dirección del cliente          

      Nota: addr y addrlen se utilizan para obtener la dirección del cliente, si no necesita conocer el cliente, estos dos parámetros se establecen en NULL

  1. conectar: ​​conectarse activamente al servidor (cliente)

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

parámetro:

      sockfd --- descriptor de archivo de socket

      addr --- dirección del servidor

      addrlen --- longitud de addr

  1. leer/escribir – enviar y recibir datos

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

parámetro:

      sockfd --- descriptor de archivo de socket

      buf --- la primera dirección de los datos enviados

      len --- número de bytes enviados

      banderas --- método de envío(0)

size_t recv(int sockfd, void *buf, size_t len, int flags);

Parámetros: sockfd --- descriptor de archivo de socket

             buf --- La primera dirección del espacio donde se almacenan los datos

             len --- el número de bytes que desea recibir

             banderas --- Método de recepción (0)

  1. cerrar - cerrar el zócalo
  2. función setockopt

Enlace de referencia: https://blog.csdn.net/Mr_XJC/article/details/106788694

5.2 UDP

Pasos (ver TCP para llamadas a funciones):

(1) Crear un zócalo

(2) Vincular IP y vincular puerto

(3) Enviar y recibir mensajes

Enlace de referencia: comunicación UDP en entorno Linux_linux udp communication_workingwei's blog-CSDN blog

6. Estructura de datos

Enlace de referencia: Estructura de datos del lenguaje C_Blog de Rising Sun Chuyang-CSDN Blog

La diferencia entre estructura typedef y estructura de definición de estructura

Enlace de referencia: [lenguaje C] diferencia entre typedef struct y struct use_difference between typedef struct and direct struct_Mijie's Voice Blog-CSDN Blog

La sintaxis de struct es más complicada, así que vamos a dar ejemplos uno por uno.

Ejemplo 1:

estructura{

char a;

intb;

} X;

Aquí, se crea una variable con dos miembros,

Un carácter, un entero.

Ejemplo 2:

estructura ESTUDIANTE{

nombre del personaje;

edad int;

};

Aquí, se crea una etiqueta,

Se proporcionó un nombre de ESTUDIANTE para la lista de miembros.

En el futuro, puede declarar variables a través de struct STUDENT x;

Lo siguiente es la combinación de typedef y struct

Ejemplo tres:

estructura typedef{

nombre del personaje;

edad int;

}ALUMNO;

El efecto aquí es básicamente el mismo que en el Ejemplo 2.

ESTUDIANTE ahora es el nombre de un tipo de datos.

Las declaraciones posteriores se pueden escribir directamente como ESTUDIANTE x;

Ejemplo cuatro:

estructura typedef NODO{

datos int;

estructura NODO* siguiente;

}nodo;

Esta es una forma común de crear nodos de lista enlazada, que se puede dividir en dos pasos:

primer paso

estructura NODO{

datos int;

estructura NODO* siguiente;

};

Creó un tipo de estructura llamado NODO,

El segundo paso typedef NODE node;

Nombre el tipo de datos NODO como nodo

Cabe resaltar que

Al crear una lista enlazada,

estructura typedef NODO{

datos int;

estructura NODO* siguiente;

}nodo;

El puntero se crea usando struct NODE* next;

En las funciones posteriores de creación, inserción, eliminación y búsqueda, y en la función principal,

El puntero de declaración se unifica con el puntero de nodo*;

problemas encontrados

  1. Al compilar con múltiples subprocesos, falta la vinculación de la biblioteca y agregue -lpthread o -pthread al compilar

如:gcc -o test.c test -lpthread

  1. Problema de espacio de escaneo, dos soluciones
  1. reemplazar fgets();
  2. scanf(“%[^\n]”, mensaje);

Supongo que te gusta

Origin blog.csdn.net/qq_39825430/article/details/131982142
Recomendado
Clasificación