日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

高级Linux程序设计第五章:进程间通信

發布時間:2023/12/9 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高级Linux程序设计第五章:进程间通信 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

From:?http://www.cnblogs.com/forfuture1978/archive/2010/04/29/1723417.html

  • 五種進程間通信的方式:

    • 共享內存(shared memory):其允許多個進程通過讀寫同一塊內存地址來相互通信。

    • 內存映射(Mapped memory):其和共享內存相似,然而它是和文件系統上的一個文件相關聯的。

    • 管道(Pipe):其允許一個進程到另一個相關進程的順序通信。

    • 先入先出隊列(FIFO):和管道類似,然而因為其對應于文件系統上的文件名,可以在兩個不相關的進程間通信。

    • Socket:其允許在不同的計算機上的不同進程間通信。

1、共享內存(Shared Memory)

  • 共享內存時進程間通信方式中最快的一種,因為進程是共享同一塊內存。

  • 內核并不提供對共享內存訪問的同步機制,因而必須自己提供同步方式。

  • 要用共享內存塊,需要一個進程首先分配此內存塊。

  • 欲訪問共享內存塊的進程必須要連接到此內存塊。

  • 在使用完共享內存塊的時候,進程必須要卸載此內存塊。

  • 需要有一個進程釋放此內存塊。

  • 所有的共享內存塊都是以4KB的整數倍分配。

?

1.1、分配

  • 進程用函數shmget分配一個共享內存塊。

    • 第一個參數是共享內存塊的key

      • 不同的進程可以根據此key來訪問同一個共享內存塊。

      • 使用IPC_PRIVATE作為key會保證創建一個新的共享內存塊。

      • 如果多個進程訪問同一個共享內存塊,則必須用同一個key。

    • 第二個參數表示內存塊的大小。

    • 第三個參數是一系列標志位:

      • IPC_CREAT創建一個新的內存塊。

      • IPC_EXCL此標志位和IPC_CREAT一起使用。如果key已經存在,則此標志位使得shmget失敗。

1.2、連接(Attachment )和卸載(Detachment)

  • 一個進程需要調用shmat來連接一個共享內存。

    • 第一個參數是共享內存塊的id,由shmget返回。

    • 第二個參數是一個指針,其指向共享內存塊映射的內存地址,如果是NULL,則系統會自動選擇一個可用的內存地址。

    • 第三個參數是標志位:

      • SHM_RND表示第二個參數所指定的地址必須同頁的大小對齊。

      • SHM_RDONLY表示此內存塊只讀。

    • 此函數返回值是連接的共享內存的起始地址。

  • 共享內存塊可用函數shmdt卸載,應傳給它共享內存塊的起始地址。

  • 調用exit及exec函數自動卸載共享內存塊。

?

1.3、控制和釋放共享內存塊

  • shmctl函數可用返回和修改共享內存塊的信息。

    • 第一個參數是共享內存塊id

    • 欲得到一個共享內存塊的信息,第二個參數設為IPC_STAT,第三個參數是指向shmid_ds結構體的指針。

    • 欲刪除一個共享內存塊,第二個參數設為IPC_RMID,第三個參數設為NULL。

  • 一個共享內存塊在使用結束后,必須用shmctl顯式的釋放。

  • 調用exit和exec自動卸載共享內存塊,但是不釋放。

#include <stdio.h>

#include <sys/shm.h>

#include <sys/stat.h>

int main ()

{

??? int segment_id;

??? char* shared_memory;

??? struct shmid_ds shmbuffer;

??? int segment_size;

??? const int shared_segment_size = 0x6400;

??? /* Allocate a shared memory segment. */

??? segment_id = shmget (IPC_PRIVATE, shared_segment_size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);

??? /* Attach the shared memory segment. */

??? shared_memory = (char*) shmat (segment_id, 0, 0);

??? printf (“shared memory attached at address %p\n”, shared_memory);

??? /* Determine the segment’s size. */

??? shmctl (segment_id, IPC_STAT, &shmbuffer);

??? segment_size = shmbuffer.shm_segsz;

??? printf (“segment size: %d\n”, segment_size);

??? /* Write a string to the shared memory segment. */

??? sprintf (shared_memory, “Hello, world.”);

??? /* Detach the shared memory segment. */

??? shmdt (shared_memory);

??? /* Reattach the shared memory segment, at a different address. */

??? shared_memory = (char*) shmat (segment_id, (void*) 0x5000000, 0);

??? printf (“shared memory reattached at address %p\n”, shared_memory);

??? /* Print out the string from shared memory. */

??? printf (“%s\n”, shared_memory);

??? /* Detach the shared memory segment. */

??? shmdt (shared_memory);

??? /* Deallocate the shared memory segment. */

??? shmctl (segment_id, IPC_RMID, 0);

??? return 0;

}?

?

ipcs命令可用查看進程間通信機制的信息

使用-m可查看共享內存的信息

% ipcs -m

------ Shared Memory Segments --------

key shmid owner perms bytes nattch status

0x00000000 1627649 user 640 25600 0

ipcrm命令可刪除進程間通信對象.

% ipcrm shm 1627649

[liuchao@localhost ~]$ ipcs

------ Shared Memory Segments --------

key shmid owner perms bytes nattch status

0x00000000 196608 liuchao 600 393216 2 dest

0x764867bd 65537 liuchao 600 1 0

0x2c0056d5 98306 liuchao 600 1 0

0x500e7827 131075 liuchao 600 1 0

0x20e0f21d 163844 liuchao 600 1 0

0x00000000 229381 liuchao 600 393216 2 dest

0x00000000 262150 liuchao 600 393216 2 dest

0x00000000 294919 liuchao 600 393216 2 dest

0x00000000 327688 liuchao 600 393216 2 dest

0x00000000 360457 liuchao 600 393216 2 dest

0x00000000 393226 liuchao 600 393216 2 dest

0x00000000 425995 liuchao 600 393216 2 dest

0x00000000 458764 liuchao 600 393216 2 dest

0x00000000 491533 liuchao 600 393216 2 dest

0x00000000 557070 liuchao 600 393216 2 dest

0x00000000 589839 liuchao 600 393216 2 dest

------ Semaphore Arrays --------

key semid owner perms nsems

0x59d9bc4a 0 liuchao 600 1

0x3bd464f2 32769 liuchao 600 1

------ Message Queues --------

key msqid owner perms used-bytes messages

?

2、進程信號量

2.1、分配(Allocation)和釋放(Deallocation)

  • 調用semget分配一個信號量,調用semctl來釋放一個信號量。

  • semget的參數為一個信號量集的key,信號量集中的信號量的個數,權限標志位,返回值為信號量集id。

  • semctl的參數為信號量集的id,信號量集中的信號量的個數,IPC_RMID。

  • 當所有的使用信號量的進程結束后,信號量仍然存在。

  • 最后一個使用信號量集的進程必須顯式的刪除它。

#include <sys/ipc.h>

#include <sys/sem.h>

#include <sys/types.h>

/* We must define union semun ourselves. */

union semun {

??? int val;

??? struct semid_ds *buf;

??? unsigned short int *array;

??? struct seminfo *__buf;

};

/* Obtain a binary semaphore’s ID, allocating if necessary. */

int binary_semaphore_allocation (key_t key, int sem_flags)

{

??? return semget (key, 1, sem_flags);

}

/* Deallocate a binary semaphore. All users must have finished their

use. Returns -1 on failure. */

int binary_semaphore_deallocate (int semid)

{

??? union semun ignored_argument;

??? return semctl (semid, 1, IPC_RMID, ignored_argument);

}

2.2、初始化信號量

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

/* We must define union semun ourselves. */

union semun {

??? int val;

??? struct semid_ds *buf;

??? unsigned short int *array;

??? struct seminfo *__buf;

};

/* Initialize a binary semaphore with a value of 1. */

int binary_semaphore_initialize (int semid)

{

??? union semun argument;

??? unsigned short values[1];

??? values[0] = 1;

??? argument.array = values;

??? return semctl (semid, 0, SETALL, argument);

}

?

2.3、Wait和Post操作

  • semop函數支持wait和post操作。

    • 第一個參數是信號量集id。

    • 第二個參數是一個sembuf結構體的數組。

    • 第三個參數是數組的長度。

  • sembuf結構體:

    • sem_num是信號量集中作為操作對象的信號量的號。

    • sem_op表示對信號量的操作。如果sem_op是正數,則其將被加到信號量的值上。如果sem_op是負數,則得到其絕對值,如果此值能夠使得信號量的值為負,則阻塞當前線程,直到此信號量的值等于sem_op的絕對值。如果sem_op為零,阻塞當前線程,直到信號量的值為零。

    • sem_flg是標志位,IPC_NOWAIT使得此操作不會被阻塞,SEM_UNDO表示當進程結束的時候,系統自動取消此次操作。

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

/* Wait on a binary semaphore. Block until the semaphore value is positive, then

decrement it by 1. */

int binary_semaphore_wait (int semid)

{

??? struct sembuf operations[1];

??? /* Use the first (and only) semaphore. */

??? operations[0].sem_num = 0;

??? /* Decrement by 1. */

??? operations[0].sem_op = -1;

??? /* Permit undo’ing. */

??? operations[0].sem_flg = SEM_UNDO;

??? return semop (semid, operations, 1);

}

/* Post to a binary semaphore: increment its value by 1.

This returns immediately. */

int binary_semaphore_post (int semid)

{

??? struct sembuf operations[1];

??? /* Use the first (and only) semaphore. */

??? operations[0].sem_num = 0;

??? /* Increment by 1. */

??? operations[0].sem_op = 1;

??? /* Permit undo’ing. */

??? operations[0].sem_flg = SEM_UNDO;

??? return semop (semid, operations, 1);

}

?

3、內存映射(Mapped Memory)

3.1、映射一個普通文件

  • 使用mmap函數可將一個普通文件映射到進程內存中。

    • 第一個參數是文件將映射到的內存地址,NULL使得Linux自動選擇一個可用的地址。

    • 第二個參數是映射的長度。

    • 第三個參數是映射的內存的保護模式:PROT_READ,PROT_WRITE,PROT_EXEC。

    • 第四個參數是一個標志位:

      • MAP_FIXED表示映射的內存地址必須和頁對齊。

      • MAP_PRIVATE表示寫入映射的內存的數據不會寫入關聯的文件,而是寫入另一個文件副本,對其他線程不可見。

      • MAP_SHARED表示寫入映射的內存的數據會立即寫入關聯的文件,不會有緩存。

    • 第五個參數是關聯文件的文件描述符。

    • 第六個參數是映射的文件的偏移量。

(mmap-write.c) Write a Random Number to a Memory-Mapped File

#include <stdlib.h>

#include <stdio.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <sys/stat.h>

#include <time.h>

#include <unistd.h>

#define FILE_LENGTH 0x100

/* Return a uniformly random number in the range [low,high]. */

int random_range (unsigned const low, unsigned const high)

{

??? unsigned const range = high - low + 1;

??? return low + (int) (((double) range) * rand () / (RAND_MAX + 1.0));

}

int main (int argc, char* const argv[])

{

??? int fd;

??? void* file_memory;

??? /* Seed the random number generator. */

??? srand (time (NULL));

??? /* Prepare a file large enough to hold an unsigned integer. */

??? fd = open (argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);

??? lseek (fd, FILE_LENGTH+1, SEEK_SET);

??? write (fd, “”, 1);

??? lseek (fd, 0, SEEK_SET);

??? /* Create the memory mapping. */

??? file_memory = mmap (0, FILE_LENGTH, PROT_WRITE, MAP_SHARED, fd, 0);

??? close (fd);

??? /* Write a random integer to memory-mapped area. */

??? sprintf((char*) file_memory, “%d\n”, random_range (-100, 100));

??? /* Release the memory (unnecessary because the program exits). */

??? munmap (file_memory, FILE_LENGTH);

??? return 0;

}

(mmap-read.c) Read an Integer from a Memory-Mapped File, and Double It

#include <stdlib.h>

#include <stdio.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <sys/stat.h>

#include <unistd.h>

#define FILE_LENGTH 0x100

int main (int argc, char* const argv[])

{

??? int fd;

??? void* file_memory;

??? int integer;

??? /* Open the file. */

??? fd = open (argv[1], O_RDWR, S_IRUSR | S_IWUSR);

??? /* Create the memory mapping. */

??? file_memory = mmap (0, FILE_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

??? close (fd);

??? /* Read the integer, print it out, and double it. */

??? sscanf (file_memory, “%d”, &integer);

??? printf (“value: %d\n”, integer);

??? sprintf ((char*) file_memory, “%d\n”, 2 * integer);

??? /* Release the memory (unnecessary because the program exits). */

??? munmap (file_memory, FILE_LENGTH);

??? return 0;

}

3.2、共同訪問一個文件

  • 不同的進程可以通過將同一個文件映射到內存來通信。

  • 設置MAP_SHARD使得寫入到映射的內存的數據會立即寫入關聯的文件,并對另一個文件可見。

  • 如果不做以上設定,則Linux會對數據進行緩存,可以用函數msync將緩存寫入文件。

    • 前兩個參數表示映射的內存塊。

    • 第三個參數是標志位:

      • MS_ASTYNC:寫緩存并不立即執行。

      • MS_SYNC:寫緩存立即執行。

      • MS_INVALIDATE:所有的文件映射都被刷新,可以看到最新的更新。

msync (mem_addr, mem_length, MS_SYNC | MS_INVALIDATE);

  • 設置MAP_PRIVATE將創建一個寫即復制的映射區。寫入這些映射區的數據僅僅在當前進程可見,對其他進程不可見。

4、管道(Pipes)

4.1、創建管道

int pipe_fds[2];

int read_fd;

int write_fd;

pipe (pipe_fds);

read_fd = pipe_fds[0];

write_fd = pipe_fds[1];

4.2、用管道來進行子進程和父進程之間的通信

#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

/* Write COUNT copies of MESSAGE to STREAM, pausing for a second between each. */

void writer (const char* message, int count, FILE* stream)

{

??? for (; count > 0; --count) {

??????? /* Write the message to the stream, and send it off immediately. */

??????? fprintf (stream, “%s\n”, message);

??????? fflush (stream);

??????? /* Snooze a while. */

??????? sleep (1);

??? }

}

/* Read random strings from the stream as long as possible. */

void reader (FILE* stream)

{

??? char buffer[1024];

??? /* Read until we hit the end of the stream. fgets reads until either a newline or the end-of-file. */

??? while (!feof (stream) && !ferror (stream) && fgets (buffer, sizeof (buffer), stream) != NULL)

??????? fputs (buffer, stdout);

}

int main ()

{

??? int fds[2];

??? pid_t pid;

??? /* Create a pipe. File descriptors for the two ends of the pipe are placed in fds. */

??? pipe (fds);

??? /* Fork a child process. */

??? pid = fork ();

??? if (pid == (pid_t) 0) {

??????? FILE* stream;

??????? /* This is the child process. Close our copy of the write end of the file descriptor. */

??????? close (fds[1]);

??????? /* Convert the read file descriptor to a FILE object, and read from it. */

??????? stream = fdopen (fds[0], “r”);

??????? reader (stream);

??????? close (fds[0]);

??? }

??? else {

??????? /* This is the parent process. */

??????? FILE* stream;

??????? /* Close our copy of the read end of the file descriptor. */

??????? close (fds[0]);

??????? /* Convert the write file descriptor to a FILE object, and write to it. */

??????? stream = fdopen (fds[1], “w”);

??????? writer (“Hello, world.”, 5, stream);

??????? close (fds[1]);

??? }

??? return 0;

}

4.3、用管道重定向標準輸入,標準輸出,錯誤流。

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <unistd.h>

int main ()

{

??? int fds[2];

??? pid_t pid;

??? /* Create a pipe. File descriptors for the two ends of the pipe are placed in fds. */

??? pipe (fds);

??? /* Fork a child process. */

??? pid = fork ();

??? if (pid == (pid_t) 0) {

??????? /* This is the child process. Close our copy of the write end of the file descriptor. */

??????? close (fds[1]);

??????? /* Connect the read end of the pipe to standard input. */

??????? dup2 (fds[0], STDIN_FILENO);

??????? /* Replace the child process with the “sort” program. */

??????? execlp (“sort”, “sort”, 0);

??? }

??? else {

??????? /* This is the parent process. */

??????? FILE* stream;

??????? /* Close our copy of the read end of the file descriptor. */

??????? close (fds[0]);

??????? /* Convert the write file descriptor to a FILE object, and write to it. */

??????? stream = fdopen (fds[1], “w”);

??????? fprintf (stream, “This is a test.\n”);

??????? fprintf (stream, “Hello, world.\n”);

??????? fprintf (stream, “My dog has fleas.\n”);

??????? fprintf (stream, “This program is great.\n”);

??????? fprintf (stream, “One fish, two fish.\n”);

??????? fflush (stream);

??????? close (fds[1]);

??????? /* Wait for the child process to finish. */

??????? waitpid (pid, NULL, 0);

?? }

?? return 0;

}

4.4、打開(popen)和關閉(pclose)管道

#include <stdio.h>

#include <unistd.h>

int main ()

{

??? FILE* stream = popen (“sort”, “w”);

??? fprintf (stream, “This is a test.\n”);

??? fprintf (stream, “Hello, world.\n”);

??? fprintf (stream, “My dog has fleas.\n”);

??? fprintf (stream, “This program is great.\n”);

??? fprintf (stream, “One fish, two fish.\n”);

??? return pclose (stream);

}

4.5、先進先出隊列(FIFOs)

  • 一個先進先出隊列是一個管道,只不過在文件系統中有文件名與之對應。

  • FIFOs又被稱為命名管道。

  • mkfifo命令可以創建一個FIFO

?

% mkfifo /tmp/fifo

% ls -l /tmp/fifo

prw-rw-rw- 1 samuel users 0 Jan 16 14:04 /tmp/fifo

  • mkfifo函數可以創建一個FIFO

  • 第一個參數是文件系統中的路徑。

  • 第二個參數是權限。

  • 訪問FIFO和訪問一個普通文件相同。

  • 如果兩個進程通過FIFO進行通信,則需要一個進程打開一個FIFO用于寫,另一個進程打開同一個FIFO用于讀。

5、套接字(Sockets)

  • 創建一個套接字:

    • 命名空間:PF_LOCAL和PF_UNIX表示本地命名空間,PF_INET表示互聯網命名空間。

    • 通信方式:SOCK_STREAM表示面向連接的套接字,SOCK_DGRAM表示面向數據報的套接字。

  • 關閉套接字:close

  • 連接套接字:欲在客戶端和服務器段建立連接,客戶端調用connect,指向服務器的地址,服務器端等待accept連接。

  • 綁定套接字:bind,將套接字綁定到一個地址。

  • 監聽套接字:listen,使得服務器監聽一個端口,等待accept一個連接。

  • 接受套接字:accept,接受一個來自客戶端的連接。

?

5.1、本地命名空間套接字

訪問同一臺機器的套接字可以使用本地命名空間:PF_LOCAL和PF_UNIX

(socket-server.c) Local Namespace Socket Server

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/socket.h>

#include <sys/un.h>

#include <unistd.h>

/* Read text from the socket and print it out. Continue until the

socket closes. Return nonzero if the client sent a “quit”

message, zero otherwise. */

int server (int client_socket)

{

??? while (1) {

??????? int length;

??????? char* text;

??????? /* First, read the length of the text message from the socket. If read returns zero, the client closed the connection. */

??????? if (read (client_socket, &length, sizeof (length)) == 0)

??????????? return 0;

??????? /* Allocate a buffer to hold the text. */

??????? text = (char*) malloc (length);

??????? /* Read the text itself, and print it. */

??????? read (client_socket, text, length);

??????? printf (“%s\n”, text);

??????? /* Free the buffer. */

??????? free (text);

??????? /* If the client sent the message “quit,” we’re all done. */

??????? if (!strcmp (text, “quit”))

??????????? return 1;

??? }

}

int main (int argc, char* const argv[])

{

??? const char* const socket_name = argv[1];

??? int socket_fd;

??? struct sockaddr_un name;

??? int client_sent_quit_message;

??? /* Create the socket. */

??? socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0);

??? /* Indicate that this is a server. */

??? name.sun_family = AF_LOCAL;

??? strcpy (name.sun_path, socket_name);

??? bind (socket_fd, &name, SUN_LEN (&name));

??? /* Listen for connections. */

??? listen (socket_fd, 5);

??? /* Repeatedly accept connections, spinning off one server() to deal with each client. Continue until a client sends a “quit” message. */

??? do {

??????? struct sockaddr_un client_name;

??????? socklen_t client_name_len;

??????? int client_socket_fd;

??????? /* Accept a connection. */

??????? client_socket_fd = accept (socket_fd, &client_name, &client_name_len);

??????? /* Handle the connection. */

??????? client_sent_quit_message = server (client_socket_fd);

??????? /* Close our end of the connection. */

??????? close (client_socket_fd);

??? } while (!client_sent_quit_message);

??? /* Remove the socket file. */

??? close (socket_fd);

??? unlink (socket_name);

??? return 0;

}

(socket-client.c) Local Namespace Socket Client

#include <stdio.h>

#include <string.h>

#include <sys/socket.h>

#include <sys/un.h>

#include <unistd.h>

/* Write TEXT to the socket given by file descriptor SOCKET_FD. */

void write_text (int socket_fd, const char* text)

{

??? /* Write the number of bytes in the string, including NUL-termination. */

??? int length = strlen (text) + 1;

??? write (socket_fd, &length, sizeof (length));

??? /* Write the string. */

??? write (socket_fd, text, length);

}

int main (int argc, char* const argv[])

{

??? const char* const socket_name = argv[1];

??? const char* const message = argv[2];

??? int socket_fd;

??? struct sockaddr_un name;

??? /* Create the socket. */

??? socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0);

??? /* Store the server’s name in the socket address. */

??? name.sun_family = AF_LOCAL;

??? strcpy (name.sun_path, socket_name);

??? /* Connect the socket. */

??? connect (socket_fd, &name, SUN_LEN (&name));

??? /* Write the text on the command line to the socket. */

??? write_text (socket_fd, message);

??? close (socket_fd);

??? return 0;

}

?

5.2、互聯網套接字

(socket-inet.c) Read from a WWW Server

#include <stdlib.h>

#include <stdio.h>

#include <netinet/in.h>

#include <netdb.h>

#include <sys/socket.h>

#include <unistd.h>

#include <string.h>

/* Print the contents of the home page for the server’s socket. Return an indication of success. */

void get_home_page (int socket_fd)

{

??? char buffer[10000];

??? ssize_t number_characters_read;

??? /* Send the HTTP GET command for the home page. */

??? sprintf (buffer, “GET /\n”);

??? write (socket_fd, buffer, strlen (buffer));

??? /* Read from the socket. The call to read may not

??? return all the data at one time, so keep trying until we run out. */

??? while (1) {

??????? number_characters_read = read (socket_fd, buffer, 10000);

??????? if (number_characters_read == 0)

??????????? return;

??????? /* Write the data to standard output. */

??????? fwrite (buffer, sizeof (char), number_characters_read, stdout);

??? }

}

int main (int argc, char* const argv[])

{

??? int socket_fd;

??? struct sockaddr_in name;

??? struct hostent* hostinfo;

??? /* Create the socket. */

??? socket_fd = socket (PF_INET, SOCK_STREAM, 0);

??? /* Store the server’s name in the socket address. */

??? name.sin_family = AF_INET;

??? /* Convert from strings to numbers. */

??? hostinfo = gethostbyname (argv[1]);

??? if (hostinfo == NULL)

??????? return 1;

??? else

??????? name.sin_addr = *((struct in_addr *) hostinfo->h_addr);

??? /* Web servers use port 80. */

??? name.sin_port = htons (80);

??? /* Connect to the Web server */

??? if (connect (socket_fd, &name, sizeof (struct sockaddr_in)) == -1) {

??????? perror (“connect”);

??????? return 1;

??? }

??? /* Retrieve the server’s home page. */

??? get_home_page (socket_fd);

??? return 0;

}


總結

以上是生活随笔為你收集整理的高级Linux程序设计第五章:进程间通信的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。