Interprocess communication article from: UNIX snack of: (2001-10-06 07:05:00)
Process Communication is a very important knowledge in UNIX.
There is three ways to produce a new process: 1, fork call; 2, system call; 3, Exec call; we often say that the process communication programming mainly has the following three methods: 1, Message Queue queue programming; 2, TCP / IP Socket programming; 3, shared memory programming; 1. Process call 1, generating process fork call example: fork () function: Create a new process. Syntax: #include #include PID_T fork (); Description: This system calls generates a new process, a sub-process, a replica called a process. Calling process is called the father process, the child process inherits almost all the properties of the parent process:. Actual UID, GID and effective UID, GID.. Environment variable.. Additional gid.. Close sign when calling Exec (). UID Settings the mode bit.. GID Settings the mode bit... Process group number... Conversation ID Control terminal. The current work directory.. The root directory.. File creates a mask umask.. File length limits ULIMIT.. Subsequent value, such as priority, and any other process predetermined parameters, depending on the species different decisions. There are also some other properties. But the child process also has different properties different from the parent process:. Process number, child process number different from the process group number. Parent process number.. Sub process inherits the file descriptor of the Parent process Or the flow time, there is a copy of your own and share this resource with the parent process and other sub-process. The user time and system time of the child process are initialized to 0.. The timeout clock of the child process is set to 0.. Signal of child processes The processing function pointer is set to be empty. The child process does not inherits the record lock of the Parent process. Return Value: Returns the child process back to 0, the parent process returns the sub-process number, which is also the most convenient way to distinguish the parent-child process. Returns -1 to the parent process, the child process does not generate. Example: PID_T PID; IF ((pID = fork ())> 0) {/ * Parent Process Process * /} else == 0 {/ * Child process processing process * / exit (0); / * CEO must use exit () to exit * /} else {printf ("fork error / n"); exit (0);} 2, Generating Process SYSTEM Call Example: Function: Generate a new process, the child process executes the specified command. Syntax: #include #include INT System (String) Char * string; The command can exist as the command interpreter. This command can be the same as the command line command, but because the command is placed in the system call, you should pay attention to the processing of special meaning characters when compiling. Command lookup is the Path environment The definition of the variable is generally not impact on the parent process. Return value: When the parameter is an empty pointer, only the return value is not zero when the command interpreter is valid. If the parameter is not an empty pointer, return The value of the return status of this command (with WaitPID ()) return value. The command is invalid or syntax error returns a non-zero value, and the command executed is terminated. The other case returns -1. Example 1: Char Command [81] ; int i; for (i = 1; i <8; i ) {sprintf (Command, "PS -T TTY% 02i", I); System (Command);}: CHAR Befehl [200]; / * String buffer for csh command * / char * runserver = "hosts1";
/ * Server name * / short shift_act_l; / * curRect Shift Number * / char shift_Act_c [1]; char shift_beg [20]; / * Shift begin * / char shift_end [20]; / * Shift end * / .... T_report_p-> shift_no = '0'; memcpy (t_report_p-> time_from, "YYYY-MM-DD HH: MI: SS", sizeof (t_report_p-> time_from); memcpy (t_report_p-> time_to, "YYYY-mm- DD HH: MI: SS ", SIZEOF (t_report_p-> time_to)); MEMSET (Befehl, '/ 0', SIZEOF (Befehl)); Sprintf (Befehl," RSH% S% Sprot.sh '% S% S%) C / ".19s/ "/".19s/" /"%9.9s/ "0 '&", RunServer, Report_RSH_PATH, PROD_LOG, DRUCKER_NAME_1, T_REPORT_P-> Shift_no, t_report_p-> time_from, t_report_p-> time_to, T_report_p-> Coil_ID); System (Befehl); 3, Generating Process EXEC () Call Example: Exec () Features: Performing a File Syntax: #include int execl (path, arg0, ..., argn (char *) 0) Char * path, * arg0, ..., * argn; int execv (path, argv) char * path, * argv []; int execle (pat, arg0, ..., argn, (char *) 0, ENVP) char * path, * arg0, ..., * argn, * envp []; int execve (path, argv, envp) char * path, * argv [], * envp []; Int Execvp (File, Argv) Char * file, * argv []; Description: This is a system called family, used for Turn a new program into the memory, and overwrite, generating a new memory process image. The new program can be an executable or shell batch command. When the C program is executed, it is called : main (int Argc, char * argv [], char * envp []); Argc is the number of parameters, is the array of various parameter string pointer, and ENVP is a pointer array of environment variable strings for new processes .argc at least 1 , Argv [0] is the program file name, so, in the above EXEC system call family, PATH is the path name of the new process file, file is the new process file name. If File is not a full path name, the system call will press the PATH environment Variables automatically find the corresponding executable run. If the new process file is not an executable target file (such as a batch file), execlp () and execvp () will form the file as a standard input of a command interpreter. System (). arg0, ... and other pointers point to '/ 0'
The end of the string, which makes up the valid parameters of the new process, and the list is ended at an empty pointer. In turn, Arg0 must exist and point to the new process file name or path name. Similarly, Argv is a string pointer array, argv [ 0] Point to the new process file name or path name, and end with an empty pointer. ENVP is a string pointer array, ending with a null pointer, which forms a new process environment. In calling these system calls, the file refers to the file finger The new process is also open, unless it has defined a Close-ON-EXEC flag. The open file pointer remains unchanged in the new process, all related file locks are also reserved. Call process settings are being captured Signals are restored to default settings in new processes, others remain unchanged. The new process starts up the UID and GID of the SUID and SGID settings defined files when the file starts. The new process has inherited the following properties: Additional gid.. Process number.. Process group number.. Session number. Control terminal.. ALARM clock signal remains.. Current work directory... Resource restrictions. User time, system time, child process user time, child process system time.. Record lock. Process signal mask.. Signal mask.. Priority.. For schedule. After calling success, system call modification The latest access time of the new process file. Return value: The system call generally does not have successful return values, because the original process has not been unfaised. Example: Printf ("Now this process will be ps command / n"); Execl "/ bin / ps", "ps", "- ef", null; second, process communication program 1, Message Queue queue programming example / ***************** *********************************************************** ********* Excerpt from "Linux Programmer's Guide - Chapter 6" (C) Opyright 1994-1995, Scott Burkett ***************************** *********************************************************** ****** MODULE: Msgtool.c ************************************************************ ******************************* ************* A Command Line Tool for Tinkering with Sysv Style Message Queues ************************************ *********************************************************** * / #include #include #include #include #include #include #define MAX_SEND_SIZE 80 struct mymsgbuf {long mtype; char mtext [MAX_SEND_SIZE];}; void send_message (int qid, struct mymsgbuf * qbuf, long type, char * text); void read_message (int qid, struct mymsgbuf * qbuf, long type ); void transove_queue (int qid); int qid, char * mode); void usage (void); int main (int Argc, char * argv []) {key_t key; int msgqueue_id;
Struct mymsgbuf qbuf; if (argc == 1) usage (); / * CREATE UNIQUE Key via call to ftok () * / / * key = ftok (".", 'W'); * / key = 123456; printf ("Key =% D / N", Key); key = ipc_private; / * open the queue - create if Necessary * / IF ((TOLOWER (Argv [1]))))! = 's') {IF ((msgqueue_id = msgget (key, ipc_creat | 066)) == -1) {Perror ("msgget"); exit (1);} Printf ("msgqueue_id =% d / n", msgqueue_id);} Switch (TOLOWER (Argv [1] [0])) {CASE 'S': Send_Message (ATOI (Argv [4]), (Struct Mymsgbuf *) & QBUF, ATOL (Argv [2]), Argv [3]); Break; Case 'r': read_message (msgqueue_id, & qbuf, atol (argv [2])); break; case 'd': remove_queue (atoi (argv [2])); remove_queue (msgqueue_id); break; case 'm': change_queue_mode (Msgqueue_ID, Argv [2]); Break; default: usage ();} return (0);} void send_message (int qid, struct mymsgbuf * qbuf, long type, char * text) {printf ("msgqueue_id =% d) / N ", QID); / * send a message to the queue * / printf (" sending a message ... / n "); QBUF-> mtype = type; strcpy (qbuf-> mtext, text); printf "TYPE:% ld text:% s / n", qbuf-> mty PE, QBUF-> mText); IF ((Msgsnd (Struct Msgbuf *) QBUF, Strlen (QBUF-> mText) 1, 0)) == - 1) {Perror ("msgsnd"); EXIT 1);}} void read_message (int qid, struct mymsgbuf * qbuf, long type) {/ * read a message from the queue * / printf ("Reading a message ... / n"); QBUF-> mtype = type ; MSGRCV (QID, Struct Msgbuf *) QBUF, Max_send_size, Type, 0); Printf ("Type:% LD Text:% S / N", QBUF-> MTYPE, QBUF-> mtext);} Void Remove_Queue (int QID) {/ * remove the queue * / msgctl (qid, ipc_rmid, 0);
} Void change_queue_mode (int qid, char * mode) {struct msqid_ds myqueue_ds; / * Get current info * / msgctl (qid, IPC_STAT, & myqueue_ds); / * Convert and load the mode * / sscanf (mode, "% ho", & myqueue_ds.msg_perm.mode); / * Update the mode * / msgctl (qid, IPC_SET, & myqueue_ds);} void usage (void) {fprintf (stderr, "msgtool - A utility for tinkering with msg queues / n"); fprintf (stderr, "/ NUSAGE: MSGTOOL (S) end / n"); fprintf (stderr, "(r) ECV / n"); fprintf (stderr, "(D ) ELETE / N "); fprintf (stderr," (m) Ode / N "); FPRINTF (stderr," NOTE: TYPE MUST BE NUMBER! / N "); EXIT (1);} 2, TCP / IP Socket Program 1), Client Party #include #include #include #include #include #include int main (int Argc, char * argv [it sockfd, newsockfd, help, seed; struct sockaddr_in peer; struct hostent * serverhost; char buff [5000]; if ( Argc <2) {fprintf (stderr, "usage: coc / n"); exit (1);} if ((Sockfd = SO) CKET (AF_INET, SOCK_STREAM, 0) <0) {Perror ("socket"); exit (1);} if ((ServerHost = gethostByname) == 0) {Perror ("gethostbyname") (1);} peer.sin_family = AF_INET; peer.sin_port = HTONS (10000); peer.sin_addr = * (Struct in_addr *) ServerHost-> h_addr_list [0]; if (connect, & peer, Sizeof) Peer)) <0) {PERROR ("Connect"); exit (1);} for (Help = 0; Help
#include #include #include Void Process (int FD) {char buff [10000]; int received; int help, read_bytes; recEived = 5000; MEMSET (BUFF, '.', Received; Read_Bytes = Read (FD, BUFF, Received); if (Read_Bytes <0) {Perror ("Read"); exit (1);} printf ("% D Bytes Have Received on Socket% D / N ", READ_BYTES, FD); Printf (" BUFF = / N% S / N ", BUFF); for (Help = 0; Help #include #include #define shmkey 74 #define k 1024 int shmid; cleanup () {shmctl (shmid, ipc_rmid , 0); exit (0);} main () {int * Pint; char * addr1, * addr2; extern char * shmat ();
Extern cleanup (); for (i = 0; i <20; i ) Signal (i, cleanup); shmid = shmget (shmKey, 128 * k, 0777 | ipc_creat); addr1 = shmat (shmid, 0,0); Addr2 = shmat (SHMID, 0, 0); Printf ("ADDR1 0x% x addr2 0x% x / n", addr1, addr2); PINT = (int *) addr1; for (i = 0; i <256; i * Pint = I; PINT = (int *) addr1; * pint = 256; PINT = (int *) addr2; for (i = 0; i <256; i ) printf ("index% d / TValue% D / n ", i, * pint ; shmdt (addr1); shmdt (addr2); pause ();} example 2 1), creation and write sharing memory: / * incrudes * / #include #include < Stdio.h> #include #include #include #include #include typedef struct {int tc_number CHAR AP_NAME [5]; Char mymessage [20];} Comm_Table; main () {/ * local variables * / int RET = 0; key_t key; int = 0; communication = 0; Comm_Table * Comm_reg; key = FTOK (".", 'W'); / * CREATE A Share Memory if NOT EXIST * / IF ((shm_id = shmget), IPC_CREAT | IPC_EXCL | 0666)) == -1) { / * Share Memory Has Been Created * / IF ((SHM_ID = Shmget (key, sizeof (comm_table), 0)) == -1) {print f ("Error =% D / N", Errno; Return (RET);}} Comm_REG = (Comm_Table *) Shmat (SHM_ID, (Char *) 0, SHM_SHARE_MMU); Comm_Reg-> TC_Number = 56110563;} 2) Read Shared Memory, Remove Shared Memory: / * Includes * / #include #include #include #include #include #include #include typedef struct {int TC_Number; char ap_name [5]; char mymessage [20];} comm_table; main () {/ * local variables * / int RET = 0;