📜  相关系统调用(系统V)(1)

📅  最后修改于: 2023-12-03 15:27:16.897000             🧑  作者: Mango

相关系统调用(System V)

在UNIX/Linux系统中,系统调用是应用程序与操作系统之间的接口,允许应用程序请求操作系统提供的服务和资源。System V是UNIX操作系统中的一个版本,其中包含了许多常用的系统调用。以下是一些常见的System V系统调用和用法:

进程控制
fork()

fork()系统调用用于创建一个新进程,该进程称为子进程,它是调用进程(即父进程)的副本。子进程从调用fork()之后的代码行开始执行,而父进程则继续执行其原来的代码。

#include <unistd.h>
#include <stdio.h>
int main() {
  pid_t pid = fork();
  if (pid == 0) {
    printf("Child process\n");
  } else {
    printf("Parent process, child PID=%d\n", pid);
  }
  return 0;
}
wait()

wait()系统调用用于使进程等待其子进程结束,并获取子进程的退出状态。

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
  pid_t pid = fork();
  if (pid == 0) {
    printf("Child process\n");
    exit(42);
  } else {
    int status;
    wait(&status);
    if (WIFEXITED(status)) {
      printf("Child exited with status %d\n", WEXITSTATUS(status));
    }
  }
  return 0;
}
exec()

exec()系列系统调用用于将当前进程替换为新进程映像。execve()是其中最通用的一个,它允许指定新进程的路径、命令行参数和环境变量。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
  char *argv[] = { "/bin/ls", "-l", NULL };
  char *envp[] = { NULL };
  execve(argv[0], argv, envp);
  perror("execve");
  return 1;
}
文件操作
open()

open()系统调用用于打开一个文件,并返回文件描述符(文件句柄)。如果文件不存在,则可以使用相应的标志创建新文件。

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
  int fd = open("file.txt", O_CREAT | O_WRONLY, 0666);
  if (fd == -1) {
    perror("open");
    return 1;
  }
  write(fd, "Hello, world!\n", 14);
  close(fd);
  return 0;
}
read()

read()系统调用用于从文件描述符读取数据,并将其存储在缓冲区中。返回值是读取的字节数,如果到达文件末尾则返回0,出错则返回-1。

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_SIZE 1024
int main() {
  int fd = open("file.txt", O_RDONLY);
  if (fd == -1) {
    perror("open");
    return 1;
  }
  char buf[BUF_SIZE];
  int n;
  while ((n = read(fd, buf, BUF_SIZE)) != 0) {
    if (n == -1) {
      perror("read");
      close(fd);
      return 1;
    }
    write(STDOUT_FILENO, buf, n);
  }
  close(fd);
  return 0;
}
write()

write()系统调用用于将数据从缓冲区写入文件描述符。它返回成功写入的字节数,如果出错则返回-1。

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_SIZE 1024
int main() {
  int fd = open("file.txt", O_WRONLY | O_APPEND);
  if (fd == -1) {
    perror("open");
    return 1;
  }
  char buf[BUF_SIZE] = "Hello again, world!\n";
  int n = write(fd, buf, strlen(buf));
  if (n == -1) {
    perror("write");
    close(fd);
    return 1;
  }
  close(fd);
  return 0;
}
进程间通信
pipe()

pipe()系统调用创建一个半双工管道(即只能单向传递数据的管道),并返回两个文件描述符作为结果。它通常由父进程在fork()之后的代码中使用,用于与子进程通信。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
  int fd[2];
  if (pipe(fd) == -1) {
    perror("pipe");
    return 1;
  }
  pid_t pid = fork();
  if (pid == -1) {
    perror("fork");
    return 1;
  } else if (pid == 0) {
    close(fd[1]);
    char buf;
    while (read(fd[0], &buf, 1) > 0) {
      write(STDOUT_FILENO, &buf, 1);
    }
    close(fd[0]);
    _exit(EXIT_SUCCESS);
  } else {
    close(fd[0]);
    char *message = "Hello, world!\n";
    write(fd[1], message, strlen(message));
    close(fd[1]);
    wait(NULL);
  }
  return 0;
}
msgget()

msgget()系统调用创建或打开一个消息队列,并返回其标识符。标识符由系统内部维护,可以用于后续的系统调用。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
struct my_message {
  long mtype;
  char mtext[80];
};
int main() {
  key_t key = ftok(".", 'a');
  if (key == -1) {
    perror("ftok");
    return 1;
  }
  int msqid = msgget(key, IPC_CREAT | 0666);
  if (msqid == -1) {
    perror("msgget");
    return 1;
  }
  struct my_message message;
  message.mtype = 1;
  strncpy(message.mtext, "Hello, world!", 80);
  if (msgsnd(msqid, &message, strlen(message.mtext) + 1, 0) == -1) {
    perror("msgsnd");
    return 1;
  }
  sleep(1);
  if (msgrcv(msqid, &message, 80, 0, 0) == -1) {
    perror("msgrcv");
    return 1;
  }
  printf("Received message: %s\n", message.mtext);
  if (msgctl(msqid, IPC_RMID, NULL) == -1) {
    perror("msgctl");
    return 1;
  }
  return 0;
}
shmget()

shmget()系统调用创建或打开一个共享内存段,并返回其标识符。标识符由系统内部维护,可以用于后续的系统调用。

#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
  int shmid = shmget(IPC_PRIVATE, 8, IPC_CREAT | 0666);
  if (shmid == -1) {
    perror("shmget");
    return 1;
  }
  char *data = shmat(shmid, NULL, 0);
  if (data == (char *) -1) {
    perror("shmat");
    return 1;
  }
  strncpy(data, "hello", 8);
  if (shmdt(data) == -1) {
    perror("shmdt");
    return 1;
  }
  return 0;
}
线程操作
pthread_create()

pthread_create()系统调用创建一个新的线程,并将其执行起点设置为指定的函数。线程的参数可以通过一个指针传递。

#include <pthread.h>
#include <stdio.h>
void *thread_func(void *arg) {
  int n = *(int *)arg;
  printf("Thread running. Argument: %d\n", n);
  return NULL;
}
int main() {
  pthread_t thread;
  int arg = 42;
  if (pthread_create(&thread, NULL, thread_func, &arg) != 0) {
    perror("pthread_create");
    return 1;
  }
  pthread_join(thread, NULL);
  return 0;
}
pthread_mutex_lock()

pthread_mutex_lock()pthread_mutex_unlock()系统调用用于控制对共享资源的访问,以避免竞态条件(race condition)。在使用共享资源之前,线程可以调用pthread_mutex_lock(),以获得互斥锁;在使用完后,必须调用pthread_mutex_unlock(),以释放该锁。

#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int shared_resource = 0;
void *thread_func(void *arg) {
  pthread_mutex_lock(&mutex);
  shared_resource++;
  printf("Thread running. Resource value: %d\n", shared_resource);
  pthread_mutex_unlock(&mutex);
  return NULL;
}
#define NUM_THREADS 10
int main() {
  pthread_t threads[NUM_THREADS];
  for (int i = 0; i < NUM_THREADS; i++) {
    if (pthread_create(&threads[i], NULL, thread_func, NULL) != 0) {
      perror("pthread_create");
      return 1;
    }
  }
  for (int i = 0; i < NUM_THREADS; i++) {
    pthread_join(threads[i], NULL);
  }
  return 0;
}

以上是一些常见的System V系统调用和用法,它们是UNIX/Linux编程的基础,值得程序员深入学习。